当前位置:   article > 正文

Linux中的常用命令指令(四万字零基础超全详解)_目前在/ home 这个目录下,如果想要进入/ var / log 这个目录时,可以怎么写呢?

目前在/ home 这个目录下,如果想要进入/ var / log 这个目录时,可以怎么写呢?

前言

本篇博文介绍了Linux 下的一些常用指令,举了很多个范例去讲解每一种指令的用法,还对范例进行了分析。希望各位小伙伴不能只看,还要多加练习,自己将下面的范例完成一遍,才会有收获。博主相信,当你掌握了这篇博文的内容,就可以完全入门Linux 了。让我们开始学习/复习吧!!

一、帮助指令

1. man 指令(获得帮助信息)

功能描述:获得其他指令或者配置文件的帮助信息。

基本语法:man + [命令或配置文件]
  • 1

举例:查看 ls 命令的帮助信息。命令如下:

[dmtsai@study ~]$ man ls
  • 1

结果如下:

LS(1)   General Commands Manual     LS(1)
NAME
       ls, dir, vdir - 列目录内容
提要
       ls [选项] [文件名...]
       POSIX 标准选项: [-CFRacdilqrtu1]
GNU 选项 (短格式):
       [-1abcdfgiklmnopqrstuxABCDFGLNQRSUX]   [-w   cols]   [-T   cols]   [-I  pattern]  [--full-time]  [--format={long,verbose,commas,across,vertical,single-column}]
       [--sort={none,time,size,extension}] [--time={atime,access,use,ctime,status}] [--color[={none,auto,always}]] [--help] [--version] [--]

描述( DESCRIPTION )
       程序ls先列出非目录的文件项,然后是每一个目录中的“可显示”文件。如果没有选项之外的参数【译注:即文件名部分为空】出现,缺省为 "." (当前目录)。 
       选项“ -d ”使得目录与非目录项同样对待。除非“ -a ” 选项出现,文件名以“.”开始的文件不属“可显示”文件。
       
       以当前目录为准,每一组文件(包括非目录文件项,以及每一内含文件的目录)分别按文件名比较顺序排序。如果“-l ”选项存在,每组文件前显示一摘要行:给出该组文件长度之和(以 512 字节为单位)。
       
       输出是到标准输出( stdout )。除非以“ -C ”选项要求按多列输出,输出 将是一行一个。然而,输出到终端时,单列输出或多列输出是不确定的。可以分别用选项“ -1 ” 或“ -C ”来强制按单列或多列输出。
.....(后面省略).....
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

分析:man 指令可以获得其后接的命令/配置文件的帮助信息。

在上面我们获得了ls指令的帮助信息,我们可以知道,在Linux 中,隐藏文件以.开头,并且每个指令的多个选项可以组合使用,比如指令ls -al,如下:

[dmtsai@study ~]$ ls -al

总用量 128
dr-xr-x---. 17 root root  4096 66 12:19 .
dr-xr-xr-x. 19 root root  4096 418 19:12 ..
-rw-------.  1 root root 16096 65 15:49 .bash_history
-rw-r--r--.  1 root root   193 331 09:49 .bash_profile
.....(后面省略).....
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

分析:使用 ls 指令时,将其-a-l 选项组合使用,就可以将目录里面所有文件的详细信息按行输出了。

2. help 指令

功能描述:获得 shell 内置命令的帮助信息。

基本语法:help + [命令] 
  • 1

举例:查看 history 命令的帮助信息。命令如下:

[dmtsai@study ~]$ help history
  • 1

结果如下:

history: history [-c] [-d 偏移量] [n]history -anrw [文件名]history -ps 参数 [参数...]
    显示或操纵历史列表。
    带行号显示历史列表,将每个被修改的条目加上前缀 '*'。
    参数 N 会仅列出最后的 N 个条目。
    选项:
      -c	删除所有条目从而清空历史列表。
      -d 	偏移量	从指定位置删除历史列表。
      -a	将当前绘画的历史行追加到历史文件中。
      -n	从历史文件中读取所有未被读取的行。
      -r	读取历史文件并将内容追加到历史列表中。
      -w	将当前历史写入到历史文件中,并追加到历史列表中。
      -p	对每一个 ARG 参数展开历史并显示结果,而不存储到历史列表中。
      -s	以单条记录追加 ARG 到历史列表中。
.....(后面省略).....
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

分析:使用 help 指令可以显示其后接Linux内置命令(如cd,history等)的帮助信息,对我们使用指令帮助巨大。

二、目录与路径指令

1. 相对路径与绝对路径

绝对路径: 由根目录/开始写起的文件名或目录路径, 例如:/home/dmtsai/.bashrc

相对路径: 某个文件相对于当前文件的路径。 例如:./home/dmtsai../. ./home/dmtsai/等等。反正开头不是/就属于相对路径的写法。

相对路径是以“你当前文件所在路径的相对位置”来表示的。举例来说,假如你目前在/home这个目录下, 如果想要进入/var/log这个目录时,可以怎么写呢?如下:

写法一: [dmtsai@study ~]$ cd /var/log    #(absolute) 绝对路径

写法二: [dmtsai@study ~]$ cd ../var/log  #(relative) 相对路径
  • 1
  • 2
  • 3

解释:

  • cd (change directory),这是用来变换工作目录的指令,后面还会详细介绍。

  • 目前在 /home 目录下面,所以要回到上一层目录 ../ 之后,才能继续往 /var 目录移动。

特别注意这两个特殊的目录:
.:代表当前目录,也可以使用 ./ 来表示;
..:代表上一层目录,也可以 ../ 来代表。
这个...目录概念是很重要的,你常常会看到 cd .../command 之类的指令下达方式。

例题:如何先进入/var/spool/mail/目录,再进入到/var/spool/cron/目录内?
答:由于 /var/spool/mail /var/spool/cron 同样在 /var/spool/ 目录中,因此最简单的指令下达方法为:

[dmtsai@study ~]$ cd /var/spool/mail 

[dmtsai@study ~]$ cd ../cron
  • 1
  • 2
  • 3

相对路径的用途:

  • 如果需要使用很长的路径名时,比如: 现在你正在/cluster/raid/output/taiwan2006/smoke 这个目录下工作,而另一个目录在 /cluster/raid/output/taiwan2006/cctm 路径下,那么从第一个要到第二个目录去的话,怎么写比较方便?当然是使用cd . ./cctm 了。

绝对路径的用途:

  • 但是对于文件名的正确性来说,绝对路径的正确度更好。 一般来说,如果是在写程序 (shell scripts) 来管理系统的条件下,务必使用绝对路径的写法。 虽然绝对路径的写法比较麻烦,但是这个写法绝对不会有问题。 如果在程序中使用相对路径,则可能由于你执行程序的工作环境不同,导致一些问题的发生。

2. 目录的相关操作

2.1 特殊目录

有一些比较特殊的目录需要记下来才行,如下表:

目录代表含义
.代表的当前目录
..代表上一层目录
-代表用户所在的上一个目录
~代表“目前使用者身份”所在的主文件夹
~account代表 account 这个使用者的主文件夹(account是个帐号名称)
  • 特别注意:在所有目录下面都会存在的两个目录( . )与 ( . . ) ,分别代表此层与上层目录的意思。
  • 例题:请问在Linux下面,根目录(/)下有没有上层目录(. .)存在? 答:若使用“ ls -al / ”指令去查询, 可以看到根目录下确实存在( . )与( . . )两个目录,再仔细的查阅, 可发现这两个目录的属性与权限完全一致,这代表根目录的上一层(. .)与根目录自己( . )是同一个目录。

2.2 cd(change directory, 变换目录)

  • cd 是 Change Directory 的缩写,这是用来变换工作目录的指令。注意,目录名称与 cd 指令之间存在一个空格。
  • dmtsai 用户的主文件夹是/home/dmtsai/,而root 用户的主文件夹则是/root/,假设我以root 身份在 Linux系统中,那么简单的说明一下上面特殊目录的意义,如下:
[dmtsai@study ~]$ su - # 先切换身份成为 root。

[root@study ~] cd [相对路径或绝对路径] 
# 最重要的就是目录的绝对路径与相对路径,还有一些特殊目录的符号。

[root@study ~] cd ~dmtsai 
# 代表去到 dmtsai 这个使用者的主文件夹,亦即 /home/dmtsai 

[root@study dmtsai] cd ~ 
# 表示回到自己的主文件夹,亦即是 /root 这个目录;

[root@study ~] cd 
# 没有加上任何路径,也还是代表回到自己主文件夹的意思;

[root@study ~] cd .. 
# 表示去到目前的上层目录,亦即是 /root 的上层目录即根目录(/)的意思; 

[root@study /] cd - 
# 表示回到刚刚的那个目录,也就是 /root 

[root@study ~] cd /var/spool/mail 
# 这个就是绝对路径的写法!直接指定要去的完整路径名称;

[root@study mail] cd ../postfix 
# 这个是相对路径的写法,我们由/var/spool/mail 
# 去到/var/spool/postfix 就这样写。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 分析: 一登陆Linux系统后,每个帐号都会在自己帐号的主文件夹中。那回到上一层目录可以用“ cd . . ”, 利用相对路径的写法必须要确认你目前的路径才能正确的去到想要去的目录。
  • 例如上表当中最后一个例子, 你必须要确认你是在/var/spool/mail当中,并且知道 在/var/spool当中有个postfix 目录,这样才能使用cd . ./postfix 去到正确的目录, 否则就要直接输入" cd /var/spool/postfix "这个绝对路径了。
  • 其实,在提示字符 [root@study mail] 当中,已经指出当前的目录是 mail了。

2.3 pwd(显示目前所在的目录)

  • pwd 是 Print Working Directory 的缩写,也就是显示目前所在目录的指令。
  • 用法如下:
[root@study ~] pwd [-P] 
选项与参数: 
-P :显示出正确的路径,而非使用链接 (link) 路径。 

范例:单纯显示出目前的工作目录: 
[root@study ~] pwd 

/root # 显示出目前的工作目录 

范例:显示出实际的工作目录,而非链接文件本身的目录名而已 
[root@study ~] cd /var/mail 
#注意,/var/mail是一个链接文件 

[root@study mail] pwd 
/var/mail  #列出目前的工作目录 

[root@study mail] pwd -P 
/var/spool/mail  #加了选项 -P 后出现不同

[root@study mail] ls -ld /var/mail 
lrwxrwxrwx. 1 root root 10 May 4 17:51 /var/mail -> spool/mail
 # 因为 /var/mail 是链接文件,链接到 /var/spool/mail 文件上,
 # 所以,加上 pwd -P 的选项后,输出不以链接文件的数据显示,而是显示正确的完整路径。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 分析:Linux提示字符仅列出结尾那一个目录名称,这个时候你可以使用 pwd 指令来得到目前工作的完整目录路径。而 -P 的选项可以让我们取得正确的目录路径,而不是以链接文件的路径来显示。

2.4 mkdir (创建新目录)

  • 用法如下:
[root@study ~] mkdir [-mp] 目录名称
选项与参数: 
-m :设置文件的权限。直接设置,不需要默认权限 (umask) 。
-p :帮助你直接将所需要的目录(包含上层目录)递回创建起来。

范例:请到/tmp下面尝试创建数个新目录看看: 
[root@study ~] cd /tmp 
[root@study tmp] mkdir test #创建一名为 test 的新目录,成功。

[root@study tmp] mkdir test1/test2/test3/test4 
# 我想直接创建多层目录,会失败,系统返回:
mkdir: cannot create directory ‘test1/test2/test3/test4’: No such file or directory 
# 系统返回,不能创建这个目录。 

[root@study tmp] mkdir -p test1/test2/test3/test4 
# 原来要创建 test4 前需要先创建 test3 。加了这个 -p 的选项,系统可以自行递归创建多层目录,不需要再一层一层创建。

范例:创建权限为rwx--x--x的目录 
[root@study tmp] mkdir -m 711 test2 

[root@study tmp] ls -ld test* 
drwxr-xr-x. 2 root root 6 Jun 4 19:03 test 
drwxr-xr-x. 3 root root 18 Jun 4 19:04 test1 
drwx--x--x. 2 root root 6 Jun 4 19:05 test2 
# 仔细看上面的权限部分,如果没有加上 -m 来强制设置属性,系统会使用默认属性。 如果看不懂默认权限的小伙伴可以忽略本例,我们会在其他章节介绍文件权限的内容。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 分析:在默认的情况 下, 你所需要的目录得一层一层的创建。例如:假如你要创建一个目录为 /home/bird/testing/test1,那么首先必须要有 /home ,然后创建 /home/bird ,再创建 /home/bird/testing ,最后才可以创建 /home/bird/testing/test1 这个目录。假如没有 /home/bird/testing ,就不能创建 test1 目录。
  • 不过,直接下达:“ mkdir -p /home/bird/testing/test1 ” ,系统就会自动的帮你将 /home, /home/bird, /home/bird/testing 依序的创建起目录。并且, 如果该目录本来就已经存在时,系统也不会显示错误讯息。
  • 另外,我们可以利用 -m 选项在创建新目录时来强制给予该目录相关的权限, 例如上例,我们使用" -m 711 "来给予新的目录 drwx–x–x 的权限,若不使用 -m 选项,则新目录的权限是默认权限。

2.5 rmdir (删除“空”的目录)

  • 用法如下:
[root@study ~] rmdir [-p] 目录名称 
选项与参数: 
-p :连同“上层”“空的”目录也一起删除 

范例:将于mkdir范例中创建的目录(/tmp下面)删除掉
[root@study tmp] ls -ld test* # 看看有多少目录存在? 
drwxr-xr-x. 2 root root 6 Jun 4 19:03 test 
drwxr-xr-x. 3 root root 18 Jun 4 19:04 test1 
drwx--x--x. 2 root root 6 Jun 4 19:05 test2 

[root@study tmp] rmdir test # 可直接删除掉最末尾的目录,没问题。 

[root@study tmp] rmdir test1 
# 因为test1 目录下尚有内容,所以无法删除!系统返回: 
rmdir: failed to remove ‘test1’: Directory not empty 

[root@study tmp] rmdir -p test1/test2/test3/test4 

[root@study tmp] ls -ld test* 
# 下面的输出中test与test1不见了。
drwx--x--x. 2 root root 6 Jun 4 19:05 test2 
# 利用 -p 这个选项,立刻就可以将 test1/test2/test3/test4 一次删除;
# 不过要注意的是,这个 rmdir 仅能“删除空的目录”。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 分析:如果想要删除旧有的目录时,就使用 rmdir 指令。例如将刚刚创建的test 目录删除,使用“ rmdir test ”即可。请注意,目录需要一层一层的删除才行!而且被删除的目录里面必定不能存在其他的目录或文件。 这也是所谓的空的目录(empty directory)的意思。
  • 那如果要将所有目录下的东西都杀掉呢? 这个时候就必须使用“ rm -r test ”指令了。不过,还是使用 rmdir 比较安全,你也可以尝试加入 -p 的选项,来递归删除上层的空目录。

三、文件与目录管理

1. ls(文件与目录的检视)

  • 用法如下:
[root@study ~] ls [-aAdfFhilnrRSt] 文件名或目录名称.. 
[root@study ~] ls [--color={never,auto,always}] 文件名或目录名称.. 
[root@study ~] ls [--full-time] 文件名或目录名称.. 

选项与参数: 
-a :全部的文件,连同隐藏文件( 开头为 . 的文件) 一起列出来(常用) 
-A :全部的文件,连同隐藏文件,但不包括 ... 这两个目录 
-d :仅列出目录本身,而不是列出目录内的文件数据(常用) 
-f :直接列出结果,而不进行排序 (ls 默认会以文件名排序!) 
-F :根据文件、目录等信息,给予附加数据结构,例如: *:代表可可执行文件; 
				/:代表目录; =:代表 socket 文件; |:代表 FIFO 文件; 
-h :将文件大小以人类较易读的方式(例如 GB, KB 等等)列出来; 
-i :列出 inode 号码,inode 的意义下一章将会介绍; 
-l :长数据串行出,包含文件的属性与权限等等数据;(常用) 
-n :列出 UID 与 GID 而非使用者与群组的名称 (UID与GID会在帐号管理提到!) 
-r :将排序结果反向输出,例如:原本文件名由小到大,反向则为由大到小; 
-R :连同子目录内容一起列出来,等于该目录下的所有文件都会显示出来; 
-S :以文件大小大小排序,而不是用文件名排序; 
-t :依时间排序,而不是用文件名。 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 分析:在Linux系统当中,这个 ls 指令可能是最常被执行的。因为我们随时都要知道文件或者是目录的相关信息。不过,Linux文件所记录的信息实在是太多了,ls 没有需要全部都列出来。所以,当只下达 ls 时,默认显示的只有:非隐藏文件的文件名、 以文件名进行排序及文件名代表的颜色显示。举例来说, 你下达“ ls /etc ”之后,只会输出经过排序的文件名、以蓝色显示目录及白色显示一般文件。
  • 那如果还想要加入其他的显示信息,可以加入一些有用的选项。举例来 说,我们之前一直用到的 -l 选项可以显示文件详细内容,-a 选项可以将隐藏文件也显示出来等等。
  • 下面则是一些常用的范例,试做一下:
    在这里插入图片描述
  • 无论如何,ls 最常被使用到的功能还是那个 -l 的选项,为此,在默认的情况中, 已经将 ll 指令设置成为 ls -l 的意思了,也就是说,我们直接输入 ll 指令就等于是输入" ls -l "是一样的。

2. cp, rm, mv(复制、删除与移动)

2.1 cp(复制文件或目录)

  • 用法如下:
[root@study ~] cp [-adfilprsu] 来源文件(source) 目标文件(destination) 
[root@study ~] cp [options] source1 source2 source3 .... directory 
选项与参数: 
-a :相当于 -dr --preserve=all 的意思,至于 dr 请参考下列说明;(常用) 
-d :若来源文件为链接文件的属性(link file),则复制链接文件属性而非文件本身; 
-f :为强制(force)的意思,若目标文件已经存在且无法打开,则移除后再尝试一次; 
-i :若目标文件(destination)已经存在时,在覆盖时会先询问动作的进行(常用) 
-l :进行硬式链接(hard link)的链接文件创建,而非复制文件本身; 
-p :连同文件的属性(权限、用户、时间)一起复制过去,而非使用默认属性(备份常用); 
-r :递回持续复制,用于目录的复制行为;(常用) 
-s :复制成为符号链接文件 (symbolic link),亦即“捷径”文件; 
-u :destination 比 source 旧才更新 destination,或 destination 不存在的情况下才复制。 
--preserve=all :除了 -p 的权限相关参数外,还加入 SELinux 的属性, links, xattr 等也复制了。 
最后需要注意的,如果来源文件有两个以上,则最后一个目的文件一定要是“目录”才行!
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 分析:复制(cp)这个指令是非常重要的,不同身份者执行这个指令会有不同的结果产生,尤其是 -a, -p的选项, 对于不同用户来说,差异则非常大。
  • 下面的练习中,有的用户为root,有的身份为一般帐号 (这里用 dmtsai 这个帐号), 练习时请特别注意用户的差别。
[root@study ~] cp ~/.bashrc /tmp/bashrc 

[root@study ~] cp -i ~/.bashrc /tmp/bashrc 
cp: overwrite '/tmp/bashrc'? n  # n不覆盖,y为覆盖 
# 重复作两次动作,由于 /tmp 下面已经存在 bashrc 了,加上 -i 选项后, 
# 则在覆盖前会询问使用者是否确定。可以按下 n 或者 y 来二次确认。

范例二:变换目录到/tmp,并将/var/log/wtmp复制到/tmp且观察属性: 
[root@study ~] cd /tmp 
[root@study tmp] cp /var/log/wtmp . 
# 想要复制到目前的目录,最后的( . )不要忘;
[root@study tmp] ls -l /var/log/wtmp wtmp 
-rw-rw-r--. 1 root utmp 28416 Jun 11 18:56 /var/log/wtmp 
-rw-r--r--. 1 root root 28416 Jun 11 19:01 wtmp 
# 注意上面的特殊字体,在不加任何选项的情况下,文件的某些属性/权限会改变; 
# 这是个很重要的特性!要注意喔!还有,连文件创建的时间也不一样了! 
# 那如果你想要将文件的所有特性都一起复制过来该怎办?可以加上 -a 选项。
如下所示: 
[root@study tmp] cp -a /var/log/wtmp wtmp_2 

[root@study tmp] ls -l /var/log/wtmp wtmp_2 
-rw-rw-r--. 1 root utmp 28416 Jun 11 18:56 /var/log/wtmp 
-rw-rw-r--. 1 root utmp 28416 Jun 11 18:56 wtmp_2 
# 如上,整个数据特性完全一模一样。这就是 -a 的特性。

范例三:复制 /etc/ 这个目录下的所有内容到 /tmp 下面 
[root@study tmp] cp /etc/ /tmp 
# 如果是目录则不能直接复制,系统输出:
cp: omitting directory '/etc' 

[root@study tmp] cp -r /etc/ /tmp # 使用-r选项递归复制
# 还是要再次的强调, -r 是可以递归复制目录及其下面的所有文件,但是,文件与目录的权限可能会被改变;
# 所以,也可以利用“ cp -a /etc /tmp ”来下达指令,尤其是在备份的情况下。

范例四:若 ~/.bashrc 文件的内容比 /tmp/bashrc 文件的内容新才复制。 
[root@study tmp] cp -u ~/.bashrc /tmp/bashrc 
# 这个 -u 的特性,是在目标文件与来源文件有差异时,才会复制。 
# 所以,比较常被用于“备份”的工作当中

范例五:将主文件夹的 .bashrc 及 .bash_history 文件复制到 /tmp 目录下面 
[root@study tmp] cp ~/.bashrc ~/.bash_history /tmp 
# 可以将多个数据一次复制到同一个目录去,最后面一定是目录。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 分析:在默认的条件中, cp 的来源文件与目的文件的权限是不同的,目的文件的拥有者通常会是指令操作者本身。举例来说, 上面的范例二中,由于使用的是 root 身份,因此复制过来的文件拥有者与群组就改变成为 root 所有了。
  • 由于具有这个特性,因此当我们在进行备份的时候,某些需要特别注意的特殊权限文件, 例如密码档 (/etc/shadow) 以及一些配置文件,就不能直接以 cp 来复制,而必须要加上 -a 或者是 -p 等可以完整复制文件权限的选项才行。
  • 另外,如果你想要复制文件给其他的使用者, 也必须要注意到文件的权限(包含读、写、执行以及文件拥有者等等), 否则,其他人还是无法针对你给予的文件进行修订的动作。

例题:你能否使用 dmtsai 的身份,完整的复制/var/log/wtmp文件到/tmp下面,并更名为 dmtsai_wtmp呢?答:实际做看看的结果如下:

[dmtsai@study ~]$ cp -a /var/log/wtmp /tmp/dmtsai_wtmp 

[dmtsai@study ~]$ ls -l /var/log/wtmp /tmp/dmtsai_wtmp 

-rw-rw-r--. 1 dmtsai dmtsai 28416 611 18:56 /tmp/dmtsai_wtmp 
-rw-rw-r--. 1 root utmp 28416 611 18:56 /var/log/wtmp
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 分析:由于 dmtsai 用户的身份并不能随意修改文件的拥有者与群组,因此虽然能够复制 wtmp 的相关权限与时间等属性, 但是与拥有者、群组相关的,原本 dmtsai 身份无法进行的动作,即使加上 - a 选项,也是无法达成完整复制权限的效果的。

2.2 rm(移除文件或目录)

  • 用法如下:
[root@study ~] rm [-fir] 文件或目录 
选项与参数: 
-f :就是强制的意思,忽略不存在的文件,不会出现警告讯息; 
-i :互动模式,在删除前会询问使用者是否动作 ;
-r :递归删除,最常用在目录的删除了,这是非常危险的选项!!! 

范例一:将刚刚在 cp 的范例中创建的 bashrc 删除掉! 
[root@study ~] cd /tmp 
[root@study tmp] rm -i bashrc 
rm: remove regular file 'bashrc'? y 
# 如果加上 -i 的选项就会主动询问,避免你删除到错误的文件名! 

范例二:通过万用字符*的帮忙,将/tmp下面开头为bashrc的文件名通通删除: 
[root@study tmp] rm -i bashrc* 
# 注意那个星号,代表的是 0 到无穷多个任意字符。

范例三:将 cp 范例中所创建的 /tmp/etc/ 这个目录删除掉! 
[root@study tmp] rmdir /tmp/etc 
rmdir: failed to remove '/tmp/etc': Directory not empty 
# 删不掉,因为这不是空的目录,必须要加上-r 选项。

[root@study tmp] rm -r /tmp/etc 
rm: descend into directory '/tmp/etc'? y 
rm: remove regular file '/tmp/etc/fstab'? y 
rm: remove regular empty file '/tmp/etc/crypttab'? ^C 
# 按下 [crtl]+c 中断 
.....(中间省略)..... 
# 因为用户身份是 root ,默认已经加入了 -i 的选项,所以你要一直按 y 才会删除! 
# 如果不想要继续按 y ,可以按下“ [ctrl]-c ”来结束 rm 的工作。 
# 这是一种保护的动作,如果确定要删除掉此目录而不要询问,可以这样做: 
[root@study tmp] rm -rf /tmp/etc 
# 使用-f 选项可以忽略提示信息;
# 这个范例很可怕!你不要删错了!删除 /etc 目录系统是会挂掉的! 

范例四:删除一个带有 - 开头的文件 
[root@study tmp] touch ./-aaa- 
# [touch](../Text/index.html#touch)这个指令可以创建一个空文件。
[root@study tmp] ls -l 
-rw-r--r--. 1 root root 0 Jun 11 19:22 -aaa- 
# 文件大小为0,所以是空文件。 
[root@study tmp] rm -aaa- 
rm: invalid option -- 'a' # 因为 "-" 是选项嘛!所以系统误判了!
Try 'rm ./-aaa-' to remove the file '-aaa-'. 
# 新的 bash 会给出建议; 
Try 'rm --help' for more information. 

[root@study tmp] rm ./-aaa-
# 要想删除只能选择避过首位字符是 "-" 的方法,加上本目录“ ./ ”即可
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

2.3 mv(移动文件与目录,或更名)

  • 用法如下:
[root@study ~] mv [-fiu] source destination 
[root@study ~] mv [options] source1 source2 source3 ...directory 
选项与参数: 
-f :force 强制的意思,如果目标文件已经存在,不会询问而直接覆盖; 
-i :若目标文件 (destination) 已经存在时,就会询问是否覆盖;
-u :若目标文件已经存在,且 source 比较新,才会更新 (update)。

范例一:复制一文件,创建一目录,将文件移动到目录中 
[root@study ~] cd /tmp 
[root@study tmp] cp ~/.bashrc bashrc 
[root@study tmp] mkdir mvtest 
[root@study tmp] mv bashrc mvtest 
# 将某个文件移动到某个目录去,就是这样做。

范例二:将刚刚的目录名称更名为 mvtest2 
[root@study tmp] mv mvtest mvtest2  
# 当目的目录不存在时,使用mv 是将源目录更名的意思。
# 其实在 Linux 下面还有个有趣的指令,名称为 rename , 
# 该指令专职进行多个文件名的同时更名,并非针对单一文件名变更,与mv不同。请man rename。 

范例三:再创建两个文件,再全部移动到 /tmp/mvtest2 当中 
[root@study tmp] cp ~/.bashrc bashrc1 
[root@study tmp] cp ~/.bashrc bashrc2 
[root@study tmp] mv bashrc1 bashrc2 mvtest2 
# 注意,如果有多个来源文件或目录,则最后一个目标文件一定是“目录!” 
# 意思是说,将所有的数据移动到该目录的意思。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

四、文件内容查阅

1. 直接检视文件内容

1.1 cat(concatenate正向列示)

  • 用法如下:
[root@study ~] cat [-AbEnTv] 
选项与参数: 
-A :相当于 -vET 的整合选项,可列出一些特殊字符而不是空白而已; 
-b :列出行号,仅针对非空白行做行号显示,空白行不标行号! 
-E :将结尾的断行字符 $ 显示出来; 
-n :打印出行号,连同空白行也会有行号,与 -b 的选项不同; 
-T :将 [tab] 按键以 ^I 显示出来; 
-v :列出一些看不出来的特殊字符 

范例一:检阅 /etc/issue 这个文件的内容 
[root@study ~] cat /etc/issue 
\S
Kernel \r on an \m 

范例二:承上题,如果还要加印行号呢? 
[root@study ~] cat -n /etc/issue 
1 \S 
2 Kernel \r on an \m 
3 
# 所以这个文件有三行!可以印出行号,这对于大文件要找某个特定的行时有点用处 。
# 如果不想要编排空白行的行号,可以使用“cat -b /etc/issue”。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 分析:如果是一般的 DOS 文件时,就需要特别留意一些奇奇怪怪的符号, 例如断行与 [tab] 等,如果要将它们显示出来,就得加入 -A 之类的选项了。

1.2 tac(反向列示)

  • 用法如下:
[root@study ~] tac /etc/issue 
Kernel \r on an \m 
\S
# 与刚刚上面的范例一比较,是由最后一行先显示的。
  • 1
  • 2
  • 3
  • 4
  • tac 指令的选项和cat 指令的相同,可以参考上面的 cat 指令选项使用。

2. 可翻页检视

2.1 more(一页一页翻动)

  • 用法如下:
[root@study ~] more /etc/man_db.conf 
#
#
# This file is used by the man-db package to configure the man and cat paths. 
# It is also used to provide a manpath for those without one by examining 
# their PATH environment variable. For details see the manpath(5) man page. 
#
.....(中间省略)..... 
--More--(28%) # 重点在这一行,你的光标会在这里等待你的指令。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 分析:上面的范例,如果 more 后面接的文件内容行数大于屏幕输出的行数时, 就会出现类似上面的图示。重点在最后一行,最后一行会显示出目前显示的百分比, 而且还可以在最后一行输入一些有用的指令。
  • 在 more 这个程序的运行过程中,有几个按键可以按的,如下表:
按键功能
空白键 (space)代表向下翻一页
Enter代表向下翻“一行”
/字串代表在这个显示的内容当中,向下搜寻“字串”这个关键字
:f立刻显示出文件名以及目前显示的行数
q代表立刻离开 more ,不再显示该文件内容
b 或 [ctrl]-b代表往回翻页,不过这动作只对文件有用,对管线无用
  • 要离开 more 这个指令的显示工作,可以按下 q 键就能够离开了。而要向下翻页,就使用空白键即可。 比较有用的是搜寻字串的功能,举例来说,我们使用“ more /etc/man_db.conf ”来观察该文件,若想要在该文件内搜寻 MANPATH 这个字串时,可以这样做:
[root@study ~] more /etc/man_db.conf 
#
#
# This file is used by the man-db package to configure the man and cat paths. 
# It is also used to provide a manpath for those without one by examining # their PATH environment variable. For details see the manpath(5) man page. 
#
....(中间省略).... 
/MANPATH # 输入了 / 之后,光标就会自动跑到最下面一行等待输入。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 如同上面的说明,输入了( / )之后,光标就会跑到最下面一行,并且等待你的输入, 你输入了某个字串并按下[enter]之后, more 就会开始向下搜寻该字串,而且重复搜寻同一个字串, 可以直接按下 n 键即可。

2.2 less(一页一页翻动)

  • 用法如下:
[root@study ~] less /etc/man_db.conf 
#
#
# This file is used by the man-db package to configure the man and cat paths. 
# It is also used to provide a manpath for those without one by examining 
# their PATH environment variable. For details see the manpath(5) man page. 
#
.....(中间省略)..... 
:     # 重点在这一行,你的光标会在这里等待你的指令。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 分析:less 的用法比起 more 又更加的有弹性,在 more 的时候,我们并没有办法向前面翻, 只能往后面看,但若使用了 less 指令,就可以使用 [pageup] 、[pagedown] 等按键的功能来往前往后翻看文件。
  • 基本上,less 指令运行时可以输入的按键有:
按键功能
空白键向下翻动一页
[pagedown]向下翻动一页
[pageup]向上翻动一页
/字串向下搜寻“字串”的功能
?字串向上搜寻“字串”的功能
n重复前一个搜寻 (与 / 或 ? 有关!)
N反向的重复前一个搜寻 (与 / 或 ? 有关!)
g前进到这个数据的第一行去
G前进到这个数据的最后一行去 (注意大小写)
q离开 less 这个程序
  • 分析:你是否会觉得 less 使用的画面与环境与 man page 非常的类似?是因为man这个指令就是调用 less 来显示说明文档的内容的。所以我们可以在man 页面下使用上面的按键功能了。

3. 数据截取

  • 我们可以将输出的数据作一个最简单的截取,那就是取出文件前面几行 (head) 或取出后面几行 (tail) 文字的功能。 不过,要注意的是, head 与 tail 指令都是以“行”为单位来进行数据截取的。

3.1 head(取出前面几行)

  • 用法如下:
[root@study ~] head [-n number] 文件 
选项与参数: 
-n :后面接数字,代表显示几行的意思 

[root@study ~] head /etc/man_db.conf 
# 默认的情况中,显示前面十行!若要显示前 20 行,就得要这样: 
[root@study ~] head -n 20 /etc/man_db.conf 

范例:如果后面100行的数据都不打印,只打印/etc/man_db.conf的前面几行,该如何是好? 
[root@study ~] head -n -100 /etc/man_db.conf
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 分析:head 的英文意思就是“头”,它的用法自然就是显示出一个文件的前几行。 若没有加上 -n 这个选项时,默认只显示十行,若只要一行呢?那就加入“ head -n 1 filename ”即可。如果接的是负数,例如上面范例的 "-n -100"时,代表列出前面的所有行数, 但不包括最后面的100行。

3.2 tail(取出后面几行)

  • 用法如下:
[root@study ~] tail [-n number] 文件 
选项与参数: 
-n :后面接数字,代表显示几行的意思 
-f :表示持续侦测后面所接的文件名,要等到按下[ctrl]-c才会结束tail的侦测 

[root@study ~] tail /etc/man_db.conf 
# 默认的情况中,显示最后的十行!若要显示最后的 20 行,就得要这样: 
[root@study ~] tail -n 20 /etc/man_db.conf 

范例一:如果不知道/etc/man_db.conf有几行,却只想列出100行以后的数据时? 
[root@study ~] tail -n +100 /etc/man_db.conf 

范例二:持续侦测 /var/log/messages 的内容 
[root@study ~] tail -f /var/log/messages 
# 要等到输入 [crtl]-c 之后才会离开tail 这个指令的侦测。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 分析:head 自然就有 tail ( 尾巴 ) 。tail 的用法跟 head 的用法差不多类似,只是显示的是最后面几行,默认也是显示十行,若要显示非十行,就加[ -n number ]的选项即可。范例一的内容其实与" head -n -xx "有异曲同工之妙。
  • 至于范例二中,由于/var/log/messages 文件随时会有数据写入,你想要让该文件有数据写入时就立刻显示到屏幕上,就利用 -f 这个选项,它可以一直侦测 /var/log/messages 这个文件,新加入的数据都会被显示到屏幕上。 直到你按下 [crtl]-c 才会离开 tail的侦测。

例题:假如我想要显示 /etc/man_db.conf 的第 11 到第 20 行呢?

  • 答:第 11 到第 20 行,那么取前 20 行,再取后十行,所以结果就是:
    “ head -n 20 /etc/man_db.conf | tail -n 10 ”
    这样就可以得到第 11 到第 20 行之间的内容了。
  • 这两个指令中间有个管线 (|) 的符号存在,这个管线的意思是:“前面的指令所输出的讯息,请通过管线交由后续的指令继续使用”。
  • 所以," head -n 20 /etc/man_db.conf "会将文件内的 20 行取出来,但不输出到屏幕上,而是转交给后续的 tail 指令继续处理。 因此 tail 后不需要接文件名,因为 tail 所需要的数据是来自于 head 处理后的结果。(更多的管线命令,我们会在其他博文中详细解释)

4. touch(修改文件时间或创建新文件)

  • 这里只介绍创建新文件的用法,如下:
[root@study ~] touch 文件名

范例一:在/tmp目录下新建一个空的文件testtouch
[dmtsai@study ~] cd /tmp ; touch testtouch 
# 进入/tmp目录,创建一个新文件;然后使用ls 指令就可以看到新建的文件了。
[dmtsai@study tmp] ls -l testtouch 
-rw-rw-r--. 1 dmtsai dmtsai 0 Jun 16 00:45 testtouch
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 分析:在上例中,我们在两个指令之间使用了分号( ; ),代表连续指令的下达。你可以在同一行当中写入多指令, 这些指令可以“依序”执行。

5. file(观察文件类型)

  • 如果你想要知道某个文件的基本数据,例如是属于 ASCII 或者是 data 文件,或者是 binary , 且其中有没有使用到动态函数库 (share library) 等等的信息,就可以利用 file 这个指令来观察。
  • 用法如下:
[root@study ~] file ~/.bashrc 
/root/.bashrc: ASCII text # 告诉我们是 ASCII 的纯文本文件啊! 

[root@study ~] file /usr/bin/passwd 
/usr/bin/passwd: setuid ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically 
linked (uses shared libs), for GNU/Linux 2.6.32, 
BuildID[sha1]=0xbf35571e607e317bf107b9bcf65199988d0ed5ab, stripped 
# 可执行文件的数据可就多的不得了!包括这个文件的 suid 权限、相容于 Intel x86-64 等级的硬件平台 
# 使用的是 Linux 核心 2.6.32 的动态函数库链接等等。 

[root@study ~] file /var/lib/mlocate/mlocate.db 
/var/lib/mlocate/mlocate.db: data  
# 这是 data 文件!
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 分析:通过这个指令,我们可以简单的先判断这个文件的格式为何,包括未来你也可以用来判断使用 tar 指令压缩文件时,该 tarball 文件是使用哪一种压缩功能。

五、指令与文件的搜寻

1. 指令文件名的搜寻

1.1 which(寻找“可执行文件”)

  • 用法如下:
[root@study ~] which [-a] command 
选项或参数: 
-a :将所有由 PATH 目录中可以找到的指令均列出,而不止第一个被找到的指令名称 。

范例一:搜寻 ifconfig 这个指令的完整文件名 
[root@study ~] which ifconfig /sbin/ifconfig 

范例二:用 which 去找出 which 的文件名为何? 
[root@study ~] which which 
alias which='alias | /usr/bin/which --tty-only --read-alias -show-dot --show-tilde' 
	/bin/alias 
	/usr/bin/which 
# 竟然会有两个 which ,其中一个是 alias 。
# 那就是所谓的“命令别名”,意思是输入 which 会等于后面接的那串指令啦!
# 更多的数据我们会在 bash 章节中再来讨论的。

范例三:请找出 history 这个指令的完整文件名 
[root@study ~] which history 
/usr/bin/which: no history in(/usr/local/sbin:/usr/local/bin:/sbin:/bin: /usr/sbin:/usr/bin:/root/bin) 

[root@study ~] history --help 
-bash: history: --: invalid option 
history: usage: history [-c] [-d offset] [n] or history -anrw [filename] or history -ps arg 
# 系统显示无 history指令 ,但我明明可以用 root 执行 history 指令的。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 分析:which 这个指令是根据“PATH”这个环境变量所规范的路径,去搜寻“可执行文件”的文件名,重点是找出“可执行文件”。且 which 后面接的是“完整文件名”。若加上 -a 选项,则可以列出所有的可以找到的同名可执行文件,而非仅显示第一个而已。
  • 注意!最后一个范例中,history 这个常用的指令竟然找不到,这是因为 history 是“bash 内置的指令"。但是 which 默认是找 PATH 内所规范的目录,所以当然一定找不到的。

2. 文件文件名的搜寻

  • 在 Linux 下面也有相当优异的搜寻指令。通常 find 指令不常用,因为速度慢之外, 也考验硬盘。一般我们都是先使用 whereis 指令或者是 locate 指令来搜寻,如果真的找不到了,才以 find 指令来搜寻。

2.1 whereis(由一些特定的目录中寻找文件文件名)

  • 用法如下:
[root@study ~] whereis [-bmsu] 文件或目录名 
选项与参数: 
-l :可以列出 whereis 会去查询的几个主要目录而已 
-b :只找 binary 格式的文件 
-m :只找在说明文档 manual 路径下的文件 
-s :只找 source 来源文件 
-u :搜寻不在上述三个项目当中的其他特殊文件 

范例一:请找出 ifconfig 这个文件名 
[root@study ~] whereis ifconfig 
ifconfig: /sbin/ifconfig /usr/share/man/man8/ifconfig.8.gz 

范例二:只找出跟 passwd 有关的“说明文档”文件名(man page) 
[root@study ~] whereis passwd # 全部的文件名通通列出来! 
passwd:/usr/bin/passwd/etc/passwd
/usr/share/man/man1/passwd.1.gz 
/usr/share/man/man5/passwd.5.gz 

[root@study ~] whereis -m passwd 
# 只有在 man 里面的文件名才抓出来! 
passwd:/usr/share/man/man1/passwd.1.gz
/usr/share/man/man5/passwd.5.gz
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 分析:为什么 whereis 搜寻的速度会比 find 快很多,是因为 whereis 只搜寻几个特定的目录,并没有全系统去查询。 whereis 主要是针对 /bin/sbin 下面的可执行文件, 以及 /usr/share/man 下面的 man page 文件,跟几个比较特定的目录来处理。

2.2 locate(从数据库中搜索文件文件名)

  • 用法如下:
[root@study ~] locate [-ir] keyword 
选项与参数: 
-i :忽略大小写的差异; 
-c :不输出文件名,仅计算找到的文件数量 
-l :仅输出几行的意思,例如输出五行则是 -l 5 
-S :输出 locate 所使用的数据库文件的相关信息,包括该数据库纪录的文件/目录数量等 
-r :后面可接正则表达式的显示方式 

范例一:找出系统中所有与 passwd 相关的文件名,且只列出 5 个。
[root@study ~] locate -l 5 passwd 
/etc/passwd 
/etc/passwd- 
/etc/pam.d/passwd 
/etc/security/opasswd 
/usr/bin/gpasswd 

范例二:列出 locate 查询所使用的数据库文件之文件名与各数据数量。
[root@study ~] locate -S Database 
/var/lib/mlocate/mlocate.db: 
	8,086 directories # 总纪录目录数 
	109,605 files # 总纪录文件数 
	5,190,295 Bytes in file names 
	2,349,150 Bytes used to store database
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 分析: locate 指令的使用更简单,直接在后面输入“文件的部分名称”后,就能够得到结果。 以上例来说,输入 locate passwd ,那么在完整文件名 (包含路径名称) 当中,只要有 passwd 在其中,就会被显示出来。
  • 你会发现使用 locate 指令来寻找数据的时候特别快, 这是因为 locate 寻找的数据是由“已创建的数据库 /var/lib/mlocate/” 里面的数据所搜寻到的,所以不用直接去硬盘中搜寻数据。
  • 注意:locate指令搜寻是有限制的。 那么有什么限制呢?就是因为它是经由数据库来搜寻的,而数据库的创建默认是在每天执行一次,所以当你新创建起来的文件,却在数据库更新之前搜寻该文件,那么 locate 指令会告诉你找不到该文件。
  • 但是也可以手动更新数据库,直接输入“ updatedb ”即可。 updatedb 指令会去读取 /etc/updatedb.conf 这个配置文件的设置,然后再去硬盘里面进行搜寻文件名的动作, 最后就更新整个数据库文件。

2.3 find(从硬盘中搜寻文件文件名)

  • 这里只介绍一些简单的用法,find指令的搜寻功能很强大,如果有兴趣的朋友可以自己去学习一下。
  • 用法如下:
[root@study ~] find 目录 [option]
选项与参数:  
-name filename:搜寻文件名称为 filename 的文件。 
-user name :搜寻属于指定使用者的所有文件, name 为使用者帐号名称,例如 dmtsai。
-size [+-]SIZE:搜寻比 SIZE 还要大(+)或小(-)的文件。
				这个 SIZE 的规格有: c: 代表 Byte,
				k: 代表 1024Bytes。
				所以,要找比 50KB 还要大的文件,就是“ -size +50k ”。
-type TYPE :搜寻文件的类型为 TYPE 的,类型主要有:
			 一般正规文件 (f), 设备文件 (b, c), 
			 目录 (d), 链接文件 (l), 
			 socket (s), 及 FIFO (p) 等属性。 

范例一:找出文件名为 passwd 这个文件。
[root@study ~] find / -name passwd 
# 注意不要忽略 / ,这是根目录的意思。

范例二:找出文件名包含了 passwd 这个关键字的文件。 
[root@study ~] find / -name "*passwd*" 
# 利用这个 -name 可以搜寻文件名,默认是完整文件名,如果想要找关键字, 
# 可以使用通配字符( * )的任意字符来处理。

范例三:找出 /run 目录下,文件类型为 Socket 的文件名有哪些。
[root@study ~] find /run -type s 
# 这个 -type 的属性也很有帮助, 
# 例如 socket 与 FIFO 文件,可以用 find /run -type p 或 -type s 来搜寻。

范例四:搜寻 /home 下面属于 dmtsai 的文件。
[root@study ~] find /home -user dmtsai 
# 当我们要找出任何一个使用者在系统当中的所有文件时, 
# 就可以利用这个指令将属于某个使用者的所有文件都找出来。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 分析:find 指令的功能及其强大,不过由于 find 在寻找数据的时候相当的考验硬盘。所以尽量不要使用 find 指令。有更棒的指令可以取代,那就是上面提到的 whereis 与 locate 指令。

六、文件的压缩与解压

  • “压缩”与“解压缩”的动作最大的好处就是压缩过的文件大小变小了, 所以你的硬盘容量无形之中就可以容纳更多的数据。此外,在一些网络数据的传输中,也会由于文件数据量的降低, 好让网络带宽可以用来作更多的工作。

1. 常见的压缩指令

  • 在Linux的环境中,压缩文件的扩展名大多是:“ .tar, .tar.gz, .tgz, .gz, .Z, .bz2, *.xz ”,为什么会有这么多的扩展名呢?这是因为 Linux 支持的压缩指令非常多,且不同的指令所用的压缩技术并不相同,当然彼此之间可能就无法互通压缩/解压缩文件。 所以,当你下载到某个压缩文件时,自然就需要知道该文件是由哪种压缩指令所制作出来的,好用来对照着解压缩。
  • 下面列出几个常见的压缩文件扩展名:
    在这里插入图片描述
  • Linux上常见的压缩指令就是 gzip, bzip2 以及最新的 xz ,至于 compress 已经退流行了。为了支持 windows 常见的 zip,其实 Linux 也早就有 zip 指令。
  • 不过,这些指令通常仅能针对一个文件来压缩与解压缩,如此一来, 每 次压缩与解压缩都要一大堆文件。此时,那个“打包软件, tar”就显的很重要了。
  • tar 指令可以将很多文件“打包”成为一个文件,甚至是目录也可以这么玩。不过,单纯的 tar 指令功能仅是“打包”而已,即将很多文件集结成为一个文件, 事实上,它并没有提供压缩的功能。
  • 后来,GNU 计划中,将整个 tar 与压缩的功能结合在一起,如此一来便给使用者提供了更方便并且更强大的压缩与打包功能。

1.1 gzip, zcat/zmore/zless/zgrep 指令

  • 用法如下:
[dmtsai@study ~]$ gzip [-cdtv#] 文件名 
[dmtsai@study ~]$ zcat 文件名.gz 
选项与参数: 
-c :将压缩的数据输出到屏幕上,可通过数据流重导向来处理; 
-d :解压缩时使用的参数; 
-t :可以用来检验一个压缩文件的一致性,看看文件有无错误; 
-v :可以显示出原文件/压缩文件的压缩比等信息; 
-# :# 为数字的意思,代表压缩等级,-1 最快,但是压缩比最差、-9 最慢,但是压缩比最好!默认是 -6 

范例一:找出 /etc 下面 (不含子目录) 容量最大的文件,并将它复制到 /tmp ,然后以 gzip 压缩。
[dmtsai@study ~]$ ls -ldSr /etc/* 
# 忘记选项意义?请自行 man。
.....(前面省略)..... 
-rw-r--r--. 1 root root 25213 Jun 10 2014 /etc/dnsmasq.conf 
-rw-r--r--. 1 root root 69768 May 4 17:55 /etc/ld.so.cache 
-rw-r--r--. 1 root root 670293 Jun 7 2013 /etc/services 

[dmtsai@study ~]$ cd /tmp 
[dmtsai@study tmp]$ cp /etc/services .  # 注意最后有个(.)代表目的目录
[dmtsai@study tmp]$ gzip -v services 
services: 79.7% -- replaced with services.gz 

[dmtsai@study tmp]$ ll /etc/services /tmp/services* 
-rw-r--r--. 1 root root 670293 Jun 7 2013 /etc/services 
-rw-r--r--. 1 dmtsai dmtsai 136088 Jun 30 18:40 /tmp/services.gz
# 显而易见,被压缩后的文件占用空间少了很多。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 分析:当你使用 gzip 进行压缩时,在默认的状态下原本的文件会被压缩成为 .gz 的文件名,而原始文件就不再存在了。 这点与一般习惯使用 windows 做压缩的朋友所熟悉的情况不同。要注意!
  • 此外,使用 gzip 压缩的文件在 Windows 系统中,竟然可以被 WinRAR/7zip 这两个软件解压缩。至于其他的用法如下:
范例二:由于 services 是文本文件,请将范例一的压缩文件的内容读出来! 
[dmtsai@study tmp]$ zcat services.gz 
# 由于 services 这个原本的文件是是文本文件,因此我们可以尝试使用 zcat/zmore/zless 指令去读取! 
# 此时屏幕上会显示 servcies.gz 解压缩之后的原始文件内容! 

范例三:将范例一的文件解压缩。 
[dmtsai@study tmp]$ gzip -d services.gz 
# 不要使用 gunzip 这个指令解压缩,不好背!直接使用 gzip -d 来进行解压缩! 
# 与 gzip 相反, gzip -d 会将原本的 .gz 删除,回复到原本的 services 文件。 

范例四:将范例三解开的 services 用最佳的压缩比压缩,并保留原本的文件。 
[dmtsai@study tmp]$ gzip -9 -c services > services.gz 

范例五:由范例四再次创建的 services.gz 中,找出 http 这个关键字在哪几行? 
[dmtsai@study tmp]$ zgrep -n 'http' services.gz 

14:# http://www.iana.org/assignments/port-numbers 
89:http 80/tcp www www-http # WorldWideWeb HTTP 
90:http 80/udp www www-http # HyperText Transfer Protocol 
.....(下面省略).....
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 分析:范例四的重点在那个 -c 选项与( > )的使用。 -c 可以将原本要转成压缩文件的数据内容,将它变成文字类型从屏幕输出, 然后我们可以通过重定向(>) 符号,将原本应该由屏幕输出的数据,转成输出到文件,所以就能够创建出压缩档了。
  • 另外,相对于cat/more/less 指令可以使用不同的方式来读取纯文本文件,范例二中出现的 zcat/zmore/zless 指令则可以对应于 cat/more/less 的方式来读取纯文本文件被压缩后的压缩文件。
  • 另外,如果你还想要从文字压缩文件当中找数据的话,可以通过 zgrep 指令来搜寻关键字。而不需要将压缩文件解开再以 grep 进行! 这对查询备份中的文本文件数据相当有用。

1.2 bzip2,bzcat/bzmore/bzless/bzgrep 指令

  • bzip2 指令是为了取代 gzip 并提供更佳的压缩比而创造的。 bzip2 的压缩比竟然比 gzip 还要好,至于 bzip2 的用法几乎与 gzip 相同。
  • 用法如下:
[dmtsai@study ~]$ bzip2 [-cdkzv#] 文件名 
[dmtsai@study ~]$ bzcat 文件名.bz2 
选项与参数: 
-c :将压缩的过程产生的数据输出到屏幕上! 
-d :解压缩时用到的参数;
-k :保留原始文件,而不会删除原始的文件。 
-z :压缩的参数 (默认值,可以不加);
-v :可以显示出原文件/压缩文件的压缩比等信息; 
-# :与 gzip 同样的,都是在计算压缩比的参数, -9 最佳, -1 最快。 

范例一:将刚刚 gzip 范例留下来的 /tmp/services 以 bzip2 压缩。 
[dmtsai@study tmp]$ bzip2 -v services 
services: 5.409:1, 1.479 bits/Byte, 81.51% saved, 670293 in, 123932 out. 

[dmtsai@study tmp]$ ls -l services* 
-rw-r--r--. 1 dmtsai dmtsai 123932 Jun 30 18:40 services.bz2 
-rw-rw-r--. 1 dmtsai dmtsai 135489 Jun 30 18:46 services.gz 
# 此时 services 会变成 services.bz2 之外,你也可以发现 bzip2 的压缩比要较 gzip 好。
# 压缩率由 gzip 的 79% 提升到 bzip2 的 81% 了。 

范例二:将范例一的文件内容读出来! 
[dmtsai@study tmp]$ bzcat services.bz2 

范例三:将范例一的文件解压缩。 
[dmtsai@study tmp]$ bzip2 -d services.bz2 

范例四:将范例三解开的 services 用最佳的压缩比压缩,并保留原本的文件。
[dmtsai@study tmp]$ bzip2 -9 -c services > services.bz2
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 分析:看上面的范例,你会发现到 bzip2 连选项与参数都跟 gzip 一模一样。只是扩展名由 .gz 变成 .bz2 ,其他的用法都大同小异。 你也可以发现到 bzip2 的压缩率确实比 gzip 要好。不过,对于大容量文件来说,bzip2 压缩时间会花比较久。大家需要自行取舍。

1.3 xz, xzcat/xzmore/xzless/xzgrep 指令

  • 虽然 bzip2 已经具有很棒的压缩比,不过某些自由软件开发者还不满足,因此后来还推出了 xz 这个压缩比更高的指令,这个指令的用法也跟 gzip/bzip2 几乎一模一样。
  • 用法如下:
[dmtsai@study ~]$ xz [-dtlkc#] 文件名 
[dmtsai@study ~]$ xcat 文件名.xz 
选项与参数: -d :就是解压缩啊! 
-t :测试压缩文件的完整性,看有没有错误 
-l :列出压缩文件的相关信息 
-k :保留原本的文件不删除~ 
-c :同样的,就是将数据由屏幕上输出的意思! 
-# :同样的,也有较佳的压缩比的意思! 

范例一:将刚刚由 bzip2 所遗留下来的 /tmp/services 通过 xz 来压缩! 
[dmtsai@study tmp]$ xz -v services 
services (1/1) 
100 % 97.3 KiB / 654.6 KiB = 0.149 

[dmtsai@study tmp]$ ls -l services* 
-rw-rw-r--. 1 dmtsai dmtsai 123932 Jun 30 19:09 services.bz2 
-rw-rw-r--. 1 dmtsai dmtsai 135489 Jun 30 18:46 services.gz 
-rw-r--r--. 1 dmtsai dmtsai 99608 Jun 30 18:40 services.xz 
# 各位观众!看到没有啊!!容量又进一步下降的更多耶!好棒的压缩比! 

范例二:列出这个压缩文件的信息,然后读出这个压缩文件的内容。 
[dmtsai@study tmp]$ xz -l services.xz 
Strms Blocks Compressed Uncompressed Ratio Check Filename 
	1     1   97.3 KiB   654.6 KiB   0.149 CRC64 services.xz 
# 竟然可以列出这个文件的压缩前后的容量,真是太人性化了!这样观察就方便多了! 
[dmtsai@study tmp]$ xzcat services.xz 

范例三:将文件解压缩 
[dmtsai@study tmp]$ xz -d services.xz 

范例四:保留原文件的文件名,并且创建压缩文件。 
[dmtsai@study tmp]$ xz -k services
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • xz 这个压缩比真的好太多太多。以这个 services 文件为范例,它可以将 gzip 压缩比 (压缩后/压缩前) 的 21% 更进一步优化到 15%。 不过, xz 最大的问题是…压缩时间花太久了。
  • 所以,选择gzip,bzip2,xz 指令压缩文件时,要根据需求选择,不要只追求压缩比大的指令。

2. tar(打包指令)

  • 前一小节谈到的指令大多仅能针对单一文件来进行压缩,虽然 gzip, bzip2, xz 指令也能够针对目录来进行压缩。不过, 这两个指令对目录的压缩指的是“将目录内的所有文件 “分别” 进行压缩”的动作。而不像在 Windows 的系统,可以使用类似 WinRAR 这一类的压缩软件来将多个数据 “包成一个文件”的样式。
  • 这种将多个文件或目录包成一个大文件的指令功能,我们可以称呼它是一种“打包指令"。在Linux中,tar 指令可以将多个目录或文件打包成一个大文件,同时还可以通过 gzip/bzip2/xz 的支持,将该文件同时进行压缩。 更有趣的是,由于 tar 的使用太广泛了,目前 Windows 的 WinRAR 也支持 .tar.gz 文件名的解压缩。

2.1 tar

  • tar 的选项与参数非常的多,这里只讲几个常用的选项,更多选项可以自行" man tar "查询。
  • 用法如下:
[dmtsai@study ~]$ tar [选项] *.tar.gz(目的文件) filename(被打包的文件或目录)
选项与参数: 
-c :创建打包文件,可搭配 
-v :来察看过程中被打包的文件名(filename)  
-x :解打包或解压缩的功能,可以搭配 -C (大写) 在特定目录解开。
-z :通过 gzip 的支持进行压缩/解压缩:此时文件名最好为 *.tar.gz 。
-v :在压缩/解压缩的过程中,将正在处理的文件名显示出来! 
-f :-f 后面要立刻接要被处理的文件名。 
-C 目录 :这个选项用在解压缩,若要在特定目录解压缩,可以使用这个选项。

范例一:使用 tar 加入 -z 的参数备份 /etc/ 目录。
[root@study ~] tar -zcvf /root/etc.tar.gz /etc

范例二: 压缩多个文件,将 /home/pig.txt 和 /home/cat.txt 压缩成 pc.tar.gz
[root@study ~] tar -zcvf pc.tar.gz /home/pig.txt /home/cat.txt

范例三:将 pc.tar.gz 解压到当前目录。
[root@study ~] tar -zxvf pc.tar.gz

范例四:将myhome.tar.gz 解压到 /opt/tmp2目录下。
[root@study ~] mkdir /opt/tmp2  
[root@study ~] tar -zxvf /home/myhome.tar.gz -C /opt/tmp2
# 注意,在解压缩指定目录时才用到 -C这个选项。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

七、数据流重导向(>)

  • 数据流重导向 (redirect)由字面上的意思来看,好像就是将“数据传导到其他地方去”?
  • 没错,数据流重导向就是将某个指令执行后应该要出现在屏幕上的数据, 传输到其他的地方,例如文件或者是设备 (例如打印机之类的)。其在 Linux 的文字模式下非常重要,尤其是我们想要将某些数据储存下来!

1. 什么是数据流重导向

  • 一般来说,如果你要执行一个指令,通常执行流程是这样的:
    在这里插入图片描述
  • 分析:我们执行一个指令的时候,这个指令可能会由文件读入数据,经过处理之后,再将数据输出到屏幕上。 在上图当中, standard output 与 standard error output 分别代表“标准输出 (STDOUT)”与“标准错误输出 (STDERR)”, 这两个数据默认都是输出到屏幕上面。

1.1 标准输出与标准错误输出

  • standard output 与 standard error output
  • 简单的说,标准输出指的是“指令执行所回传的正确的讯息”,而标准错误输出可理解为“ 指令执行失败后,所回传的错误讯息”。
  • 举个简单例子来说,我们的系统默认有 /etc/crontab 文件但却无 /etc/vbirdsay 文件, 此时若下达“ cat /etc/crontab /etc/vbirdsay ”这个指令,cat 会进行:
    • 标准输出:读取 /etc/crontab 后,将该文件内容显示到屏幕上;
    • 标准错误输出:因为无法找到 /etc/vbirdsay,因此在屏幕上显示错误讯息。
  • 不管正确或错误的数据都是默认输出到屏幕上。那能不能通过某些机制将这两股数据分开呢? 当然可以!那就是数据流重导向的功能。
  • 数据流重导向可以 将 standard output (简称 stdout) 与 standard error output (简称 stderr) 分别传送到其他的文件或设备中去,而分别传送所用的特殊字符则如下所示:
名称对应字符
标准输入 (stdin)代码为 0 ,使用 < 或 <<
标准输出 (stdout)代码为 1 ,使用 > 或 >>
标准错误输出(stderr)代码为 2 ,使用 2> 或 2>>

1.2 标准输出(>,>>)

  • 用法如下:
范例一:观察你的系统根目录 (/) 下各目录的文件名、权限与属性,并记录下来 
[dmtsai@study ~]$ ll / # 此时屏幕会显示出文件名信息 

[dmtsai@study ~]$ ll / > ~/rootfile # 屏幕并无任何信息 

[dmtsai@study ~]$ ll ~/rootfile # 有个新文件被创建了!
-rw-rw-r--. 1 dmtsai dmtsai 1078 Jul 9 18:51 /home/dmtsai/rootfile
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 分析:屏幕怎么会完全没有数据呢?这是因为原本“ ll / ”所显示的数据已经被重新导向到 ~/rootfile 文件中了。那个 ~/rootfile 的文件名可以随便取。如果你下达“ cat ~/rootfile ”那就可以看到原本应该输出在屏幕上面的数据。
  • 如果我再次下达“ ll /home > ~/rootfile ” 后,那个 ~/rootfile 文件的内容变成什么? 它将变成“仅有 ll /home 的数据”而已。原本的“ ll / ”数据不见了吗? 是的,因为该文件的创建方式是:
    1. 该文件 (本例中是 ~/rootfile) 若不存在,系统会自动的将他创建起来,但是
    2. 当这个文件存在的时候,那么系统就会先将这个文件里面的内容清空,然后再将数据写入!
    3. 也就是若以( > )输出数据到一个已存在的文件,那个文件的原数据就会被新数据覆盖掉。
  • 那如果我想要将数据累加而不想要将旧的数据删除,那该如何是好? 利用两个大于的符号 (>>)即可。以上面的范例来说,你应该要改成“ ll / >> ~/rootfile ”。 如此一来:
    (1) ~/rootfile 不存在时系统会主动创建这个文件;
    (2) 若该文件已存在, 则新数据会在该文件原数据的最下方累加进去,而不会覆盖原数据。

1.3 标准错误输出(2>,2>>)

  • 上面谈到的是 standard output 的正确数据,那如果是 standard error output 的错误数据呢? 那就通过 2> 及 2>> ,同样是覆盖 (2>) 与累加 (2>>) 的特性。
  • 我们在刚刚才谈到 stdout 代码是 1 而 stderr 代码是 2 , 所以这个 2> 是很容易理解的,而如果仅存在 > 时,则代表默认的代码 1 。也就是说:
    • 1> :以覆盖的方法将“正确的数据”输出到指定的文件或设备上;
    • 1>> :以累加的方法将“正确的数据”输出到指定的文件或设备上;
    • 2> :以覆盖的方法将“错误的数据”输出到指定的文件或设备上;
    • 2>> :以累加的方法将“错误的数据”输出到指定的文件或设备上;

那么假如我想要将数据输出到 list 这个文件中呢?
执行“ find /home -name .bashrc > list ” 会有什么结果?

  • 你会发现 list 里面只存了那个“正确”的输出数据, 至于屏幕上还是会有错误的讯息出现。所以,如果想要将正确的与错误的数据分别存入不同的文件中需要怎么做?
范例二,将 stdout 与 stderr 分存到不同的文件去 
[dmtsai@study ~]$ find /home -name .bashrc > list_right 2> list_error
  • 1
  • 2
  • 分析:此时“屏幕上不会出现任何讯息”。因为刚刚执行的结果中,错误信息都会跑到 list_error 这个文件中,至于正确的输出数据则会存到 list_right 这个文件中了。

1.4 /dev/null 垃圾桶黑洞设备与特殊写法

如果我知道错误讯息会发生,所以要将错误讯息忽略掉而不显示或储存呢? 这个时候黑洞设备 /dev/null 就很重要了。这个 /dev/null 可以吃掉任何导向这个设备的数据,将上述的范例修订一下:

范例三,将错误的数据丢弃,屏幕上显示正确的数据 
[dmtsai@study ~]$ find /home -name .bashrc 2> /dev/null /home/dmtsai/.bashrc 
# 只有 stdout 会显示到屏幕上, stderr 被丢弃了。
  • 1
  • 2
  • 3

如果我要将正确与错误数据通通写入同一个文件去呢?这个时候就得要使用特殊的写法了! 我们同样用下面的案例来说明:

范例四:将指令的数据全部写入名为 list 的文件中 
[dmtsai@study ~]$ find /home -name .bashrc > list 2> list # 出现错误 

[dmtsai@study ~]$ find /home -name .bashrc > list 2>&1 # 正确 

[dmtsai@study ~]$ find /home -name .bashrc &> list # 正确
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 分析:上述代码第一行错误的原因是,由于两股数据同时写入一个文件,又没有使用特殊的语法, 此时两股数据可能会交叉写入该文件内,造成次序的错乱。所以虽然最终 list 文件还是会产生,但是里面的数据排列就会怪怪的,而不是原本屏幕上的输出排序。
  • 至于写入同一个文件的特殊语法如上所示,你可以使用" 2>&1 “也可以使用” &> "。

1.5 标准输入(< 与 <<)

  • 标准输入:最简单的说法来说, 就是“将原本需要由键盘输入的数据,改由文件内容来取代”的意思。 我们先由下面的 cat 指令操作来了解一下什么叫做“键盘输入”:
范例五:利用 cat 指令来创建一个文件的简单流程 
[dmtsai@study ~]$ cat > catfile 
testing 
cat file test # 这里按下 [ctrl]+d 来离开 

[dmtsai@study ~]$ cat catfile 
testing 
cat file test
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 分析:由于加入 > 在 cat 后,所以那个 catfile 文件会被主动的创建,而内容就是刚刚键盘上面输入的那两行数据了。

那能不能用纯文本文件取代键盘的输入,也就是说,用某个文件的内容 来取代键盘的敲击呢? 可以的!如下所示:

范例六:用 stdin 取代键盘的输入以创建新文件的简单流程 
[dmtsai@study ~]$ cat > catfile < ~/.bashrc 
[dmtsai@study ~]$ ll catfile ~/.bashrc 
-rw-r--r--. 1 dmtsai dmtsai 231 Mar 6 06:06 /home/dmtsai/.bashrc 
-rw-rw-r--. 1 dmtsai dmtsai 231 Jul 9 18:58 catfile 
# 注意看,这两个文件的大小会一模一样!几乎像是使用 cp 来复制一般。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 理解 < 之后,再来则是 << 这个连续两个小于的符号了。 他代表的是“结束的输入字符”的意思!

举例来讲:“我要用 cat 直接将输入的讯息输出到 catfile 中, 且当由键盘输入 eof 时,该次输入就结束”,那可以这样做:

[dmtsai@study ~]$ cat > catfile << "eof" 
> This is a test. 
> OK now stop 
>  eof # 输入这关键字,立刻就结束而不需要输入 [ctrl]+d 

[dmtsai@study ~]$ cat catfile 
This is a test. 
OK now stop # 只有这两行,不会存在关键字那一行!
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 分析:利用 << 右侧的控制字符,我们可以终止一次输入, 而不必输入 [crtl]+d 来结束,这对程序写作很有帮助。
  • 最后讲一下为何要使用命令输出重导向:
    1. 屏幕输出的信息很重要,而且我们需要将他存下来的时候;
    2. 背景执行中的程序,不希望他干扰屏幕正常的输出结果时;
    3. 一些系统的例行命令 (例如写在 /etc/crontab 中的文件) 的执行结果,希望他可以存下来时;
    4. 一些执行命令的可能已知错误讯息时,想以“ 2> /dev/null ”将他丢掉时;
    5. 错误讯息与正确讯息需要分别输出时。

八、管线命令(|)

  • 如同前面所说的, bash 命令执行的时候会有数据输出,那么如果这些数据必须经过几道手续之后才能得到我们所想要的格式,应该如何来设置?
  • 这就牵涉到管线命令的问题了(pipe),管线命令使用的是( | )这个界定符号。另外,管线命令( | )与连续下达命令的( ; )不一样。下面我们先举例来说明一下简单的管线命令。

假设我们想要知道 /etc/ 目录下面有多少文件,那么可以利用" ls /etc "来查阅,不过, 因为 /etc 下面的文件太多,导致一下子输出就将屏幕塞满了,不知道前面输出的内容是啥,此时,我们可以通过 less 指令的协助,如下:

[dmtsai@study ~]$ ls -al /etc | less
  • 1
  • 分析:使用 ls 指令输出后的内容,就能够被 less 读取,并且利用 less 的功能,我们就能够前后翻动相关的数据信息了。注意!不能直接使用" less /etc ",因为 /etc 是一个目录,而不是一个文件,less 指令是不能读取一个目录中的内容的。
  • 下面我们就来了解一下管线命令( | )的用途,其实管线命令( | )仅能处理经由前面一个指令传来的正确信息,也就是 standard output 的信息,对于 standard error 并没有直接处理的能力。 那么整体的管线命令可以使用下图表示:
    在这里插入图片描述
  • 在每个管线后面接的第一个数据必定是“指令”。而且这个指令必须要能够接受 standard input 的数据才行,这样的指令才可以是为“管线命令”,例如 less, more, head, tail 等都是可以接受 standard input 的管线命令。至于例如 ls, cp, mv 等就不是管线命令了!因为 ls, cp, mv 并不会接受来自 stdin 的数据。
  • 也就是说,管线命令主要有两个比较需要注意的地方:
    1. 管线命令仅会处理 standard output,对于 standard error output 会予以忽略;
    2. 管线命令必须要能够接受来自前一个指令的数据成为 standard input 继续处理才行。
  • 补充:如果你硬要让 standard error 输出的数据可以被管线命令所使用,那该如何处理?其实就是通过上一小节的数据流重导向即可。 让 2>&1 加入指令中,就可以让 2> 变成 1> 输出了。

1. cut, grep(截取命令)

  • 截取命令就是将一段数据经过分析后,取出我们所想要的。或者是经由分析关键字,取得我们所想要的那一行。要注意的是,截取信息通常是针对“一行一行”来分析的, 并不是整篇讯息分析。

1.1 cut

  • cut 指令可以将一段信息的某一段“切”出来,处理信息时以行为单位。
  • 用法如下:
[dmtsai@study ~]$ cut -d'分隔字符' -f fields # 用于有特定分隔字符 
[dmtsai@study ~]$ cut -c 字符区间            # 用于排列整齐的讯息 
选项与参数: 
-d :后面接分隔字符。与 -f 一起使用; 
-f :依据 -d 的分隔字符将一段讯息分区成为数段,用 -f 取出第几段的意思; 
-c :以字符 (characters) 的单位取出固定字符区间; 

范例一:将 PATH 变量取出,我要找出第五个路径。 
[dmtsai@study ~]$ echo ${PATH} 
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin 
|	   1 	  |   2    |  	   3  	   |    4 	 |	         5 	         | 	     6 	    |
[dmtsai@study ~]$ echo ${PATH} | cut -d ':' -f 5 
# 如同上面的数字显示,我们是以“ : ”作为分隔,因此会出现 /home/dmtsai/.local/bin 
# 那么如果想要列出第 3 与第 5 呢?,就是这样: 

[dmtsai@study ~]$ echo ${PATH} | cut -d ':' -f 3,5 

范例二:将 export 输出的讯息,取得第 12 字符以后的所有字串 
[dmtsai@study ~]$ export 

declare -x HISTCONTROL="ignoredups" 
declare -x HISTSIZE="1000" 
declare -x HOME="/home/dmtsai" 
declare -x HOSTNAME="study.centos.vbird" 
.....(其他省略)..... 
# 注意看,每个数据都是排列整齐的输出。
# 如果我们不想要“ declare -x ”时,就得这么做: 
[dmtsai@study ~]$ export | cut -c 12- 

HISTCONTROL="ignoredups" 
HISTSIZE="1000" 
HOME="/home/dmtsai" 
HOSTNAME="study.centos.vbird" 
.....(其他省略)..... 
# 知道怎么回事了吧?用 -c 可以处理比较具有格式的输出数据! 
# 我们还可以指定某个范围的值,例如第 12-20 的字符,就是 cut -c 12-20 。 

范例三:用 last 将显示的登陆者的信息中,仅留下使用者大名。
[dmtsai@study ~]$ last 

root pts/1 192.168.201.101 Sat Feb 7 12:35 still logged in 
root pts/1 192.168.201.101 Fri Feb 6 12:13 - 18:46 (06:33) 
root pts/1 192.168.201.254 Thu Feb 5 22:37 - 23:53 (01:16) 
# last 可以输出“帐号/终端机/来源/日期时间”的数据,并且是排列整齐的。

[dmtsai@study ~]$ last | cut -d ' ' -f 1 
# 由输出的结果我们可以发现第一个空白分隔的字段代表帐号,所以使用如上指令: 
# 但是因为 root pts/1 之间空格有好几个,并非仅有一个,所以,如果要找出 
# pts/1 其实不能以 cut -d ' ' -f 1,2 喔!输出的结果会不是我们想要的。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 分析:cut 主要的用途在于将“同一行里面的数据进行分解。”最常使用在分析一些数据或文字数据的时候, 这是因为有时候我们会以某些字符当作分区的参数,然后将数据加以切割,以取得我们所需要的数据。
  • 不过,cut 在处理多空格相连的数据时,可能会比较吃力一点,所以某些时刻可能会使用下一章的 awk 指令来取代,在这里就不赘述啦,有兴趣的小伙伴可以去我的另一篇博文看看。

1.2 grep

  • grep 用来分析一行信息, 若当中有我们所需要的信息,就将该行拿出来。
  • 用法如下:
[dmtsai@study ~]$ grep [选项] '搜寻字串' filename 
选项与参数: 
-a :将 binary 文件以 text 文件的方式搜寻数据 
-c :计算找到 '搜寻字串' 的次数 
-i :忽略大小写的不同,所有大小写视为相同 
-n :顺便输出行号 
-v :反向选择,亦即显示出没有 '搜寻字串' 内容的那一行! 

范例一:将 last 当中,有出现 root 的那一行就取出来; 
[dmtsai@study ~]$ last | grep 'root' 

范例二:与范例一相反,只要没有 root 的就取出! 
[dmtsai@study ~]$ last | grep -v 'root' 

范例三:在 last 的输出讯息中,只要有 root 就取出,并且仅取第一栏 
[dmtsai@study ~]$ last | grep 'root' | cut -d ' ' -f1 
# 在取出 root 之后,利用上个指令 cut 的处理,就能够仅取得第一栏啰! 

范例四:取出 /etc/man_db.conf 内含 MANPATH 的那几行 
[dmtsai@study ~]$ grep 'MANPATH' /etc/man_db.conf 

....(前面省略).... 
MANPATH_MAP /usr/games /usr/share/man 
MANPATH_MAP /opt/bin /opt/man 
MANPATH_MAP /opt/sbin /opt/man 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • grep 是个很棒的指令,它支持的语法非常多,用在正则表达式中,能够处理的数据非常多。不过,我们这里先不谈正则表达式,有兴趣的小伙伴可以到我的下一篇博文中学习。这里我们先了解一下, grep 可以解析一行文字,取得关键字,若该行有存在关键字,就会将整行列出来。

2. sort,wc, uniq(排序和统计指令)

  • 很多时候,我们都会去计算一次数据里头的相同型态的数据总数,举例来说, 使用 last 可以查得系统上面有登陆主机者的身份。那么我可以针对每个使用者查出他们的总登陆次数吗?此时就得要排序与统计之类的指令来辅助了。 下面我们介绍几个好用的排序与统计指令。

2.1 sort(排序)

  • sort 指令可以帮我们将数据进行排序,而且可以依据不同的数据型态来排序。例如数字与文字的排序就不一样。此外,排序的字符与语系的编码有关,因此, 如果你需要排序时,建议使用 LANG=C 来让语系统一,这样数据排序比较好一些。
  • 用法如下:
[dmtsai@study ~]$ sort [-fbMnrtuk] [file or stdin] 
选项与参数: 
-f :忽略大小写的差异,例如 A 与 a 视为编码相同; 
-b :忽略最前面的空白字符部分; 
-M :以月份的名字来排序,例如 JAN, DEC 等等的排序方法; 
-n :使用“纯数字”进行排序(默认是以文字体态来排序的); 
-r :反向排序; -u :就是 uniq ,相同的数据中,仅出现一行代表; 
-t :分隔符号,默认是用 [tab] 键来分隔; 
-k :以那个区间 (field) 来进行排序的意思 

范例一:个人帐号都记录在 /etc/passwd 下,请将帐号进行排序。 
[dmtsai@study ~]$ cat /etc/passwd | sort 
abrt:x:173:173::/etc/abrt:/sbin/nologin 
adm:x:3:4:adm:/var/adm:/sbin/nologin 
alex:x:1001:1002::/home/alex:/bin/bash 
# 省略很多的输出,由上面的数据看,sort 是默认“以第一个”数据来排序, 
# 而且默认是以“文字”型态来排序的,所以由 a 开始排到最后。 

范例二:/etc/passwd 内容是以 : 来分隔的,我想以第三栏来排序,该如何? 
[dmtsai@study ~]$ cat /etc/passwd | sort -t ':' -k 3 

root:x:0:0:root:/root:/bin/bash 
dmtsai:x:1000:1000:dmtsai:/home/dmtsai:/bin/bash 
alex:x:1001:1002::/home/alex:/bin/bash 
arod:x:1002:1003::/home/arod:/bin/bash 
# 如果是以文字体态来排序的话,原本就会是这样,想要使用数字排序: 
# cat /etc/passwd | sort -t ':' -k 3 -n 
# 必须用 -n 选项来告知 sort 以数字来排序。

范例三:利用 last ,将输出的数据仅取帐号,并加以排序 
[dmtsai@study ~]$ last | cut -d ' ' -f1 | sort
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 分析:上面的范例二中要注意的是,虽然我们选择依据第三栏的数字来进行排列,但系统默认是以文字体态来排序(比如1096是会排在110前面的),若是想让系统依据数字大小进行排序,我们就得加上 -n 选项,(此时110就会排在1096前面啦)。

2.2 uniq(过滤重复数据)

  • 如果我排序完成了,想要将重复的数据仅列出一个显示,就可以 uniq 指令了。
  • 用法如下:
[dmtsai@study ~]$ uniq [-ic] 
选项与参数: 
-i :忽略大小写字符的不同; 
-c :进行计数 

范例一:使用 last 将帐号列出,仅取出帐号栏,进行排序后仅取出一位; 
[dmtsai@study ~]$ last | cut -d ' ' -f1 | sort | uniq 

范例二:承上题,如果我还想要知道每个人的登陆总次数呢? 
[dmtsai@study ~]$ last | cut -d ' ' -f1 | sort | uniq -c 

1  # 啥都没有代表空白行
6 (unknown 
47 dmtsai 
4 reboot 
7 root 
1 wtmp 
# 从上面的结果可以发现 reboot 有 4 次, root 登陆则有 7 次。大部分是以 dmtsai 来操作。
 # wtmp 与第一行的空白行都是 last 的默认字符,那两个可以忽略。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 分析:这个指令用来将“重复的行删除掉只显示一个”,举个例子来说, 你要知道这个月份登陆你主机的使用者有谁,而不在乎他的登陆次数,那么就使用上面的范例, (1)先将所有的数据列出;(2)再将人名独立出来;(3)经过排序;(4)只显示一个。
  • 由于uniq 这个指令是在将重复的东西减少,所以当然需配合 sort 指令对排序过的文件处理。

2.3 wc(统计数据)

  • 如果我想要知道 /etc/man_db.conf 这个文件里面有多少字?多少行?多少字符的话, 可以利用 wc 这个指令来达成,它可以帮我们统计输出的讯息的整体数据。
  • 用法如下:
[dmtsai@study ~]$ wc [-lwm] 
选项与参数: 
-l :仅列出行; 
-w :仅列出多少字(英文单字); 
-m :多少字符; 

范例一:那个 /etc/man_db.conf 里面到底有多少相关字、行、字符数? [dmtsai@study ~]$ cat /etc/man_db.conf | wc 
131 723 5171 
# 输出的三个数字中,分别代表: “行、字数、字符数” 

范例二:我知道使用 last 可以输出登陆者,但是 last 最后两行并非帐号内容,那么请问, 我该如何以一行指令串取得登陆系统的总人次? 
[dmtsai@study ~]$ last | grep [a-zA-Z] | grep -v 'wtmp' | grep -v 'reboot' |  grep -v 'unknown' | wc -l 
# 由于 last 会输出空白行, wtmp, unknown, reboot 等无关帐号登陆的信息,
# 因此,利用 grep 取出非空白行,以及去除上述关键字那几行,再计算行数即可。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 分析:wc 是相当有用的计算文件内容的一个工具组,举例来说,当你要知道目前你的帐号文件中有多少个帐号时,就使用这个方法:“ cat /etc/passwd | wc -l ”。因为 /etc/passwd 里头一行代表一个使用者,所以知道行数就能知道有多少的帐号在里面了。

3. tee(双向重导向)

  • 想个简单的东西,我们由前一节知道( > )会将数据流整个传送给文件或设备,因此我们除非去读取该文件或设备,否则就无法继续利用这个数据流。如果想要将这个数据流的处理过程中将某段讯息存下来,利用 tee 指令就可以了。
    在这里插入图片描述

  • tee 指令会同时将数据流分送到文件去与屏幕 (screen);而输出到屏幕的数据其实就是 stdout , 这样就可以通过管道( | )让下个指令继续处理了。

  • 用法如下:

[dmtsai@study ~]$ tee [-a] file 
选项与参数: 
-a :以累加 (append) 的方式,将数据加入 file 当中! 

[dmtsai@study ~]$ last | tee last.list | cut -d " " -f1 
# 这个范例可以让我们将 last 的输出的数据存一份到 last.list 文件中,
# 同时屏幕会输出使用 cut 指令处理后的数据。

[dmtsai@study ~]$ ls -l /home | tee ~/homefile | more 

# 这个范例则是将 ls 的数据存一份到 ~/homefile ,同时屏幕也有输出数据; 

[dmtsai@study ~]$ ls -l / | tee -a ~/homefile | more 

# 要注意!默认情况下 tee 指令后接的文件会被覆盖,若加上 -a 这个选项则能将数据累加。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 分析:tee 指令可以让标准输出数据转存一份到文件内并将同样的数据继续输出到屏幕去处理。这样除了可以让我们同时分析一份数据并记录下来之外,还可以作为处理一份数据的中间暂存盘记录之用,非常好用。

4. paste(粘贴两个文件)

  • paste 指令可以直接将两个文件的同一行行贴在一起,且中间以 [tab] 键隔开。
  • 用法如下:
[dmtsai@study ~]$ paste [-d] file1 file2 
选项与参数: 
-d :后面可以接分隔字符。默认是以 [tab] 来分隔的。
-  :如果 file 部分写成 - ,表示来自 standard input 的数据的意思。 

范例一:用 root 身份,将 /etc/passwd 与 /etc/shadow 同一行贴在一起。
[root@study ~] paste /etc/passwd /etc/shadow 

root:x:0:0:root:/root:/bin/bash 	root:$6$wtbCCce/PxMeE5wm$KE2IfSJr...:16559:0:99999:7::: 
bin:x:1:1:bin:/bin:/sbin/nologin	bin:*:16372:0:99999:7::: 
daemon:x:2:2:daemon:/sbin:/sbin/nologin 	daemon:*:16372:0:99999:7::: 
# 注意喔!同一行中间是以 [tab] 按键隔开的! 

范例二:先将 /etc/group 读出(用 cat),然后与范例一贴上一起!且仅取出前三行 
[root@study ~] cat /etc/group | paste /etc/passwd /etc/shadow - | head -n 3 
# 这个例子的重点在( - )符号的使用,( - )符号常常代表 stdin 。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

5. 关于减号( - )的用途

  • 管线命令在 bash 的连续的处理程序中是相当重要的。另外,在 log file 的分析当中也是相当重要的一环, 所以请特别留意。
  • 在管线命令当中,常常会使用到前一个指令的 stdout 作为这次的 stdin , 某些指令需要用到文件名称 (例如 tar指令) 来进行处理时,该指令需要的 stdin 与 stdout 可以利用减号( - )来替代, 举例来说:
[root@study ~] mkdir /tmp/homeback 

[root@study ~] tar -cvf - /home | tar -xvf - -C /tmp/homeback
  • 1
  • 2
  • 3
  • 分析:上例是说,将 /home 里面的文件打包,但打包的数据不是保存到文件,而是传送到 stdout; 经过管线后,将" tar -cvf - /home “打包的stdout传送给后面的” tar -xvf - "。后面的这个( - )则是取用前一个指令的 stdout, 因此,我们就不需要使用设置文件名了。
  • 这是很常见的用法,大家需要注意。

九、重点回顾

  • 绝对路径:“一定由根目录( / )写起”;相对路径:“不由( / )写起,而是由相对与当前目录写起” 。
  • 特殊目录有:., . ., -, ~, ~account 需要注意;
  • 与目录相关的指令有:cd, mkdir, rmdir, pwd 等重要指令;
  • rmdir 仅能删除空目录,要删除非空目录需使用“ rm -r ”指令
  • 使用者能使用的指令是依据 PATH 变量所规定的目录去搜寻的;
  • ls 可以检视文件的属性,尤其 -d, -a, -l 等选项特别重要!
  • 文件的复制、删除、移动可以分别使用:cp, rm, mv等指令来操作;
  • 检查文件的内容(读档)可使用的指令包括有:cat, tac, more, less, head, tail 等 。cat -n 可显示行号。
  • touch 可用来创建空文件;
  • 观察文件的类型可以使用 file 指令来观察;
  • 搜寻指令的完整文件名可用 which 或 type ,这两个指令都是通过 PATH 变量来搜寻文件名;
  • 搜寻文件的完整文件名可以使用 whereis 找特定目录或 locate 到数据库去搜寻,而不实际搜寻文件系统;
  • 利用 find 可以加入许多选项来直接查询文件系统,以获得自己想要知道的文件名。
  • 压缩指令为通过一些运算方法去将原本的文件进行压缩,以减少文件所占用的磁盘容量。 压缩前与压缩后的文件所占用的磁盘容量比值, 就可以被称为是“压缩比” 。
  • 压缩的好处是可以减少磁盘容量的浪费,在 WWW 网站也可以利用文件压缩的技术来进行数据的传送,好让网站带宽的可利用率上升喔
  • *压缩文件的扩展名大多是:“.gz, .bz2, .xz, .tar, .tar.gz, .tar.bz2, .tar.xz”。
  • 常见的压缩指令有 gzip, bzip2, xz。压缩率最佳的是 xz,若可以不计时间成本,建议使用 xz 进行压缩。
  • tar 可以用来进行文件打包,并可支持 gzip, bzip2, xz 的压缩。
    • 压 缩:tar -zcvf filename.tar.xz 被压缩的文件或目录
    • 解压缩:tar -zcvf filename.tar.xz -C 指定解压缩的目录
  • 数据流重导向通过 >, 2>, < 之类的符号将输出的信息转到其他文件或设备去。
  • 管线命令的重点是:“管线命令仅会处理 standard output,对于 standard error output 会予以忽略” ;“管线命令必须要能够接受来自前一个指令的数据成为 standard input 继续处理才行。”
  • 本章介绍的管线命令主要有:cut, grep, sort, wc, uniq, tee, paste 等。

总结

  • 本学期学习了Linux操作系统实践课程,最近临近期末,小白博主便做了一个Linux常用指令用法整理总结,可以方便自己在期末进行复习,也希望可以帮到需要的同学。
  • 本篇博文是博主参考《鸟哥的Linux私房菜》一书其中几章内容学习整理的,加上自己的理解,删删减减。如果有兴趣的同学可以去看看原书,那个才是宝藏,在这里也感谢一下鸟哥,虽然他可能不认识我哈哈。
  • 本文中没有将 进程管理和正则表达式这两部分内容整理进来,而这两部分内容也是期末考察的重点,是因为小白博主之前已经分别出过两篇博文来整理了,也放在博主的 Linux专栏下,想要学习的朋友可以自行查看。
  • 小白博主觉得,只要把这篇文章看懂,理解并将每个范例自己敲一遍,期末就可以稳过了哈哈。
  • 最后,小白博主整理这篇文章花了挺多时间。如果本文有什么不足之处,请各位大佬在评论区批评指正;如果本文对您有帮助的话,就给小白博主点个赞吧!!欢迎在评论区交流学习!
  • 祝大家期末科科4.0,让我们在下一篇博文再见吧!!
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/83128
推荐阅读
相关标签
  

闽ICP备14008679号