Linux 系统工具使用 gaunthan Posted on May 14 2016 ? Linux Basics ? ## 文件操作 ### stat `stat`用于显示文件或文件系统的状态,它会查询存储在文件的inode中的细节,如:  stat可以接收很多格式选项,可以将输出精确地限定为所需信息。如下的命令实现了类似`ls -l`的显示:  其中,`-c`选项后面是格式控制字符串,`%a`表示访问权限,`%U`表示所有者,`%G`代表所属组,`%n`代表文件名。 ### cat `cat`(concatenate,连结)通常用于连结或直接显示文件内容,如: ``` $ cat file1 This is file1. $ cat file2 This is file2. $ cat file1 file2 This is file1. This is file2. ``` cat还有一些不太常用却很有用的功能: * 行号标记 `-n`选项可以启用行号功能: ``` $ cat -n file1 file2 1 This is file1. 2 This is file2. ``` 如果要对每个文件单独标记行号,则需要对每个文件执行cat命令。 * 缩减空白行 `-s`标志会缩减重复的空白行来避免浪费空间: ``` $ cat file Hello world. $ cat -s file Hello world. ``` * 只对非空白行进行行号标记 `-b`标志忽略空白行,仅对非空白行进行标记: ``` 1 Hello 2 world. ``` * 非打印字符 不是所有文件都是文本文件,但也可以使用cat来处理这些文件。 * `-v`标志会显示文件中的非打印字符的ASCII字符: ``` $ cat -v Binfile a control key:^B ``` * `-T`标志会将tab显示地显示成`^I`,而不是在行内展开: ``` $ cat file Hello. $ cat -T file ^IHello. ``` * `-e`标志在每行的实际末尾处放置一个`$`符号,如果该行末尾有额外的空格: ``` $ echo "Hello. " > file $ cat file Hello. $ cat -e file Hello. $ ``` ### tac tac以翻转的形式输出文件的内容,如: ```Bash $ cat file Hello. John. $ tac file John. Hello ``` tac还有一个微妙的用途:向文件开头添加数据 ```Bash $ cat file cake $ (tac file;echo banana;echo apple) > tmpfile #在子shell中完成,以便让3个命令的全部写入到tmpfile $ cat tmpfile cake banana apple $ tac tmpfile > file $ cat file apple banana cake $ rm tmpfile ``` ### 重定向 #### 输出重定向 * 单个大于符号`>` 含有单个箭头的`command > filename`这样的结构在文件不存在的情况下会创建文件。如果文件确实存在,则会将其长度截短为0,但文件的inode信息依然保留。这一结构可用于写入日志文件、创建数据文件,以及执行最通用的文件创建与打开任务。如果无法写入文件,则整个命令行会失败,并且不执行任何操作。 * 双大于符号`>>` 与截短不同,一双大于符号会向已存在的文件追加内容。与单个大于符号结构相同的是,如果文件不存在,则会创建一个文件。如果没有创建或追加文件的权限,则整个命令行会失败且不执行。 ``` $ ls $ echo "Hello." > log.txt $ cat log.txt Hello. $ echo "Welcome." > log.txt $ cat log.txt Welcome. $ $ ls log.txt $ echo "Hello." >> log2.txt $ cat log2.txt Hello. $ echo "Welcome." >> log2.txt $ cat log2.txt Hello. Welcome. ``` #### 输入重定向 `commad < filename`结构使用与`>`相反的重定向,它对输入进行重定向,而不是输出。有些时候,比起使用管道从左端命令输入数据,使用输入重定向这种方式向命令输入数据会更加方便。它的一个很常见的用法是,将来自文本文件的输入传给while循环。这使得循环可以连续地读取文件中的行,然后根据情况对它们进行操作。 #### here文档 在shell脚本程序中向一条命令传递输入的一种特殊方法是使用here文档,它允许一条命令在获得输入数据时就好像是在读取一个文件或键盘一样,而实际上是从脚本程序中得到输入数据。 here文档以两个连续的小于号`<<`开始,紧跟着一个特殊的字符序列,该字符序列在文档结尾处再次出现。`<<`是shell的标签重定向符,在这里,它强制命令的输入是一个shell文档。这个特殊字符序列的作用就像一个标记,它告诉shell here文档结束的位置。因为这个标记序列不能出现在传递给命令的文档内容中,所以应该尽量使它既容易记忆又相当不寻常: ``` $ cat file #!/bin/sh cat <<!FUNKY! hello this is a here document !FUNKY! $ sh file hello this is a here document ``` here文档功能看起来相当奇怪,但其实它的作用很大。因为它可以用来调用交互式的程序,比如一个编译器,并向它提供一些事先定义好的输入。但它更常见的用途是在脚本程序中输入大量的文本,就像刚才的示例,从而可以避免用echo语句来输出每一行。可以在标识符两端都是用感叹号(!)来确保不会引起混淆。 ### dd `dd`命令使一个文件或设备中的比特流向另一个文件或设备。它也向stdrr报告读写记录的次数与整个过程花费的时间。dd是用来监视存储设备性能的理想工具: ``` $ sudo dd if=/dev/sda1 of=/dev/null bs=1024k count=1024 [sudo] password for han: 500+0 records in 500+0 records out 524288000 bytes (524 MB) copied, 6.90397 s, 75.9 MB/s ``` `if=`指定输入文件,`of=`指定输出文件。`bs=`指定复制的块大小,`count=`指定要复制的块的数量。注意,用到的设备会对性能带来极大的影响。极端的例子是/dev/zero(读取最快)、/dev/null(写入最快)以及/dev/urandom(这是一个读取非常慢的设备,因为它必须等待系统产生随机数)。存储控制器中的缓存会对速度产生巨大的影响。如果正在做性能测试(特别是在Linux下),因为Linux系统缓存也可以非常大,所以每次读取设备前执行`echo 3> /proc/sys/vm/drop_caches`,以确保缓存被完全清除再进行性能测试。 ### df `df`报告每个挂载的文件系统的未使用磁盘空间总量。通常以KB作为显示单位。 ### mktemp `mktemp`经常用来创建临时文件,并且保证文件名是唯一的。mktemp默认在/tmp目录中创建一个文件,然后在标准输出中返回文件名。可以使用指定的模板来创建文件。如果定义了\$TMPDIR,则默认模板是$TMPDIR/tmp.XXXXXXXXXX或者/tmp/tmp.XXXXXXXXXX -- 也就是/tmp/tmp.加上10个随机生成的字符(大小写字母与数字),但`mktemp /var/tmp/helloXXX会在/var/tmp中创建一个以hello开头且后面有3个随机字符的文件: ``` $ ls -l `mktemp` -rw-------. 1 han han 0 Mar 18 08:45 /tmp/tmp.SA8g10Dbdf $ ls -l `mktemp helloXXX` -rw-------. 1 han han 0 Mar 18 08:46 hellovOU ``` 还可以指定后缀。指定方法是使用`--suffix`标志或者在模板尾部使用X以外的其他字符: ``` $ ls -l `mktemp --suffix .txt` -rw-------. 1 han han 0 Mar 18 08:50 /tmp/tmp.Wn9i2Umlby.txt $ ls -l `mktemp XXXXXX.txt` -rw-------. 1 han han 0 Mar 18 08:50 IGobay.txt ``` 需要注意的是mktemp创建的文件或目录所在的目录必须存在,否则mktemp会失败。mktemp不会创建父目录(但mkdir -p)会创建父目录。例外,mktemp创建的文件的最大权限是0600,也就是说文件属主可读可写,但没有任何其他权限。如果umask比0600更加严格,则使用更严格的权限。 ### join `join`是根据两个不同文件中的公共键来组合文件的实用程序。两个文件必须按键进行排序后才能使用join。 ### install `install`是增强型的cp。它可以设置文件权限、创建目录、进行备份,以及执行更多其他操作,而且都是从单个命令行来完成。顾名思义,它编写出来是用于安装软件的脚本的,但也能用于其他目的。 由于文件已有副本可能已经被安装,所以install在安装新文件之前能够进行备份。这是通过`-b`标志来指定的,它会在新的文件名末尾使用波浪号'~'来创建备份文件。`--backup`选项可以指定其他的备份策略,如下所示: * simple或never 只是默认的波浪号'~'备份。 * numbered或者t 编号备份,如`.~1~`、`.~2~`等。 * existing或者空白 simple或者numbered,哪个使用过就用哪个(默认是simple)。 * none或者off 不进行备份。 一些常用的标志见下: * `-m`标志对模式进行指定。 格式为八进制(普通文件使用0750,rwx、r-x与---分别用于属主、属组与其他用户)或者符号格式(如`-m 'u-rwx,g=r'`)。注意,该标志对父目录不适用。父目录的创建权限是755。 * `-o`与`-g`标志告诉install文件属于哪个属主与属组。 这些标志只能被root用户使用。 * `-v`标志要求install详细地告知它所执行的操作。 ###0 grep `grep`在输入中搜索匹配传递给它的正则表达式的文本行。其最简单(与最常用)的用法是用来搜索某个固定字符串。在这种情况下,grep的标志比它的正则表达式功能更加重要。 #### grep标志 grep的4个最常用标志是: |标志|功能| |--| |-i|不区分大小写的搜索| |-l|只列出匹配文件的名称| |-w|只进行全字匹配| |-v|反选,仅列出与模式不匹配的行| 此外使用-e标志可以取代egrep来同时搜索多个模式。使用-A、-B和-C分别给出匹配行之前、之后与周围(上下文)的一定数量的文本行。 #### grep正则表达式 当传递了正则表达式时,grep使用下面的规则进行匹配。它将匹配最长的可能模式(贪婪匹配): |规则|定义| |--| |?|前项可选且最多匹配一次| |*|前项匹配零到多次| |+|前项匹配一到多次| |{n}|前项匹配n次| |{n,}|前项匹配n到多次| |{,m}|前项最多匹配m次| |{n,m}|前项最少匹配n次,最多匹配m次| ### split `split`可以基于行号对文件进行分割,但最常用来将大文件分割成较小的普通数据块(使用-b标志)。可以用各种单位指定数据块的大小,如K、M、G、T、P、E、Z,甚至Y。它们之间是1024的倍数关系。添加后缀B后将变成1000的倍数关系。split默认使用`xaa、xab···`作为后缀,使用`-d`标志可以指定使用数字作为后缀,并且自定义前缀: ``` $ ll -h total 1.1G -rw-rw-r--. 1 han han 1.0G Mar 19 13:19 bigfile $ split -b 256M -d bigfile littlefile_ #分割bigfile成256M大小的块,指定使用前缀"littlefile_"与使用数字后缀 $ $ ll -h total 2.1G -rw-rw-r--. 1 han han 1.0G Mar 19 13:19 bigfile -rw-rw-r--. 1 han han 256M Mar 19 13:24 littlefile_00 -rw-rw-r--. 1 han han 256M Mar 19 13:24 littlefile_01 -rw-rw-r--. 1 han han 256M Mar 19 13:24 littlefile_02 -rw-rw-r--. 1 han han 256M Mar 19 13:24 littlefile_03 ``` ### tee 当需要同时向标准输出与日志文件进行写操作时,我们可以使用两个`echo`语句,但需要保证对一个输出行的任意修改都会在匹配行中重复,即两次运行同一个命令行。经验告诉我们,这样的事情不会发生。何况如果命令(或管道)很长,则在这样的一个循环中,总共消耗的时间会加倍。更好的方法是使用一个命令行,将其输出同时转向标准输出与日志文件。 `tee`将输入传递到stdout,但同时也会将其写入到文件中。若使用`-a`标志,则它会对文件追加: ``` $ echo "A string." > file #输入只传递到了文件,没有传递到stdout $ cat file A string. $ echo "Another string." | tee file $ echo "Another string." | tee file Another string. $ cat file Another string. $ echo "That's all." | tee -a file #使用-a选项 That's all. $ cat file Another string. That's all. ``` ### touch `touch`是创建文件或者更新文件时间戳的程序,而且不用向文件进行任何实际的写入操作。部分选项见下: |选项|功能| |--| |-a|仅修改atime| |-c|仅修改ctime| |-m|仅修改mtime| |-d|指定ctime| |-t|使用[YYMMDDhhmm]的格式指定ctime| 文件有三个时间属性: * mtime(modification time) 当文件的内容发生变化时,就会更新这个属性。 * ctime(status time) 当文件的状态发生变化时,就会更新这个属性。如修改文件的权限和属性等。 * atime(access time) 当文件的内容被读取时,就会更新这个属性。如使用cat命令读取文件内容时。 ### find `find`工具对文件系统进行全面搜索来查看文件(包括它们的inode),并可以对它们进行各种测试,然后对匹配指定条件的文件进行某些操作。 如果只需要用文件名查找某个特定文件,并且`updatedb`命令已经在系统运行(通常使用`cron`定期调用),那么命令`locate filename`几乎会立即返回一个结果。这取决于当前文件系统中最新的文件名数据库。但如果该数据库存在,而且我们只对文件名感兴趣,那么使用locate是更好的选择。 find的参数基本上被分解为表达式与动作两部分。最常用的表达式见下表: |表达式|用途| |--| |-maxdepth levels|对文件系统树的搜索只深入到第levels层| |-mount(或者-xdev)|不跨越不同的文件系统| |-anewer filename、-cnewer filename或者-newer filename|查找比参考文件filename的访问(-anewer)时间、改变(-cnewer)时间或修改(-newer)时间更迟的文件| |-mmin n或者-mtime n|查找n分钟(-nmin)或n天(-mtime)前修改的文件| |-uid u或者-user u|查找属于用户ID(-uid)或用户名(-user u)的文件| |-gid g或者-group g|查找属于组ID(-gid)或组名(-group g)的文件| |-nouser或者-nogroup|查找不匹配属主/属组名称的文件| |-name n或者-iname n|查找名称匹配n(-iname表示不区分大小写)的文件| |-perm -g=w|查找设置了组可写位的文件(不管其他权限位)| |-perm o=r|查找权限为0500的文件(只有数组可读)| |-size n|读取大小为n的文件(后缀为b、k、M和G,整个列表与其他后缀也可以使用)| |-size +n或者-size -n|查找大小大于(+n)或小于(-n)n的文件| |-type t|查找类型为t的文件,其中t可以是d(目录)、l(链接)、f(文件)或者b、c、p、s与D| ### find -exec find的`-exec`标志使find对每个匹配的文件运行给定命令。执行给定命令时,find会将文件名放到占位符`{}`所在位置,该命令必须以分号结束。在shell中使用分号必须经过转义,即`\;`或`";"`。下面的命令对找到的每个文件执行`md5sum`,然后存储到一个临时文件中: ``` find "${DIR}" $SIZE -type f -exec md5sum {} \; | sort > $MD5 ``` ## 文本操作 ### cut `cut`用于剪切文件中每一行符合条件的段,常见的用法见下: |命令|功能| |--| |cut -c n|只剪切掉输入的每行的第n列| |cut -c m-n|剪切掉输入的每行的第m列到第 n列| |cut -d:|指定':'作为分界符| |cut -fn|只提取第n列| ### echo `echo`的基本功能是向终端显示文本序列,但它还有一些其他的功能。比如 ``` $ while true; do echo -en "^M`date`"; sleep 1; done 2016年04月 4日 9:25:23 ``` 将在终端上同一行每隔一秒显示一次时间。其中,`^M`是Ctrl+M(回车符,也称为CR或\r)。它使得光标回到一行的开头。使用到的echo的选项解释见下: |选项|功能| |--| |-e|将反斜线解释成标记特殊字符序列而不是默认的常规字符| |-n|关闭默认在行尾添加的"\r\n"| 赏 Wechat Pay Alipay Bash Shell 简介 Linux 文件权限管理