sort/uniq/tar/split/find/xargs

★ 行的排序命令sort:
1. sort命令行选项:
-t 字段之间的分隔符
-f 基于字符排序时忽略大小写
-k 定义排序的域字段,或者是基于域字段的部分数据进行排序
-m 将已排序的输入文件,合并为一个排序后的输出数据流
-n 以整数类型比较字段
-o outfile 将输出写到指定的文件
-r 倒置排序的顺序为由大到小,正常排序为由小到大
-u 只有唯一的记录,丢弃所有具有相同键值的记录
-b 忽略前面的空格
2. sort使用实例:
/> sed -n '1,5p' /etc/passwd > users
/> cat users

sort -t':' -k 2 users
-t定义了冒号为域字段之间的分隔符,-k 2指定基于第二个字段正向排序(字段顺序从1开始)。
sort -t':' -k 3r users
还是以冒号为分隔符,这次是基于第三个域字段进行倒置排序。
sort -t':' -k 6.2,6.4 -k 1r users
先以第六个域的第2个字符到第4个字符进行正向排序,在基于第一个域进行反向排序。
sort -t':' -k 6.2,6.4 -k 1 users
先以第六个域的第2个字符到第4个字符进行正向排序,在基于第一个域进行正向排序。


sort -t':' -k 1.2,1.2 users
基于第一个域的第2个字符排序
sort -t':' -k 6.2,6.4 -u users
基于第六个域的第2个字符到第4个字符进行正向排序,-u命令要求在排序时删除键值重复的行
sort -t':' -k 3 users2
基于第3个域字段以文本的形式排序
sort -t':' -k 3n users2
基于第3个域字段以数字的形式排序
ps -ef | sort -k 1 -o result
基于当前系统执行进程的owner名排序,并将排序的结果写入到result文件中

★ 删除重复行的命令uniq
uniq常用的选项如下
-c 可在每个输出行之前加上该行重复的次数
-d 仅显示重复的行
-u 显示为重复的行

/> cat testfile
    hello
    world
    friend
    hello
    world
    hello

#直接删除未经排序的文件,将会发现没有任何行被删除
 /> uniq testfile  
    hello
    world
    friend
    hello
    world
    hello

#排序之后删除了重复行,同时在行首位置输出该行重复的次数
sort testfile | uniq -c 

#仅显示存在重复的行,并在行首显示该行重复的次数
sort testfile | uniq -dc

#仅显示没有重复的行
sort testfile | uniq -uc

★ 文件压缩解压命令tar:
-c 建立压缩档案
-x 解压
--delete 从压缩包中删除已有文件,如果该文件在包中出现多次,该操作其将全部删除。
-t 查看压缩包中的文件列表
-r 向压缩归档文件末尾追加文件
-u 更新原压缩包中的文件
-z 压缩为gzip格式,或以gzip格式解压
-j 压缩为bzip2格式,或以bzip2格式解压
-v 显示压缩或解压的过程,该选项一般不适于后台操作
-f 使用档案名字,这个参数是最后一个参数,后面只能接档案名。

#将当前目录下所有文件压缩打包,需要说明的是很多人都习惯将tar工具压缩的文件的扩展名命名为.tar
tar -cvf test.tar *

tar -rvf test.tar *.log #将扩展名为.log的文件追加到test.tar包里。
tar -tvf test.tar       #查看压缩包的文件列表

/> touch install.log         #使原有的文件更新一下最新修改时间
/> tar -uvf test.tar *.log    #重新将更新后的log文件更新到test.tar中
/> tar -tvf test.tar          #从输出结果可以看出tar包中多出一个更新后install.log文件。

tar --delete install.log -f test.tar #基于上面的结果,从压缩包中删除install.log

/> rm -f users users2      #从当前目录将tar中的两个文件删除
/> tar -xvf test.tar          #解压
/> ls -l users*                 #仅列出users和users2的详细列表信息
    -rw-r--r--. 1 root root 183 Nov 11 08:02 users
    -rw-r--r--. 1 root root 279 Nov 11 08:45 users2

#以gzip的格式压缩并打包,解压时也应该以同样的格式解压,需要说明的是以该格式压缩的包习惯在扩展名后加.gz
/> tar -cvzf test.tar.gz *
/> tar -tzvf test.tar.gz      #查看压缩包中文件列表时也要加z选项(gzip格式)
    -rw-r--r-- root/root     48217 2011-11-11 22:50 install.log
    -rw-r--r-- root/root         183 2011-11-11 08:02 users
    -rw-r--r-- root/root         279 2011-11-11 08:45 users2

/> rm -f users users2 install.log
/> tar -xzvf test.tar.gz     #以gzip的格式解压
/> ls -l *.log users*
    -rw-r--r-- root/root     48217 2011-11-11 22:50 install.log
    -rw-r--r-- root/root         183 2011-11-11 08:02 users
    -rw-r--r-- root/root         279 2011-11-11 08:45 users2

/> rm -f test.*                #删除当前目录下原有的压缩包文件
#以bzip2的格式压缩并打包,解压时也应该以同样的格式解压,需要说明的是以该格式压缩的包习惯在扩展名后加.bz2
/> tar -cvjf test.tar.bz2 *
/> tar -tjvf test.tar.bz2    #查看压缩包中文件列表时也要加j选项(bzip2格式)
    -rw-r--r-- root/root     48217 2011-11-11 22:50 install.log
    -rw-r--r-- root/root         183 2011-11-11 08:02 users
    -rw-r--r-- root/root         279 2011-11-11 08:45 users2

/> rm -f *.log user*
/> tar -xjvf test.tar.bz2    #以bzip2的格式解压
/> ls -l
    -rw-r--r--. 1 root root 48217 Nov 11 22:50 install.log
    -rw-r--r--. 1 root root 10530 Nov 11 23:08 test.tar.bz2
    -rw-r--r--. 1 root root     183 Nov 11 08:02 users
    -rw-r--r--. 1 root root     279 Nov 11 08:45 users2


★ 大文件拆分命令split:
-l 指定行数,每多少分隔成一个文件,缺省值为1000行。
-b 指定字节数,支持的单位为:k和m
-C 与-b参数类似,但切割时尽量维持每行的完整性
-d 生成文件的后缀为数字,如果不指定该选项,缺省为字母

/> ls -l
    -rw-r--r--. 1 root root 10530 Nov 11 23:08 test.tar.bz2

/> split -b 5k test.tar.bz2     #以每文件5k的大小切割test.tar.bz2
/> ls -l                                #查看切割后的结果,缺省情况下拆分后的文件名为以下形式。
    -rw-r--r--. 1 root root 10530 Nov 11 23:08 test.tar.bz2
    -rw-r--r--. 1 root root   5120 Nov 11 23:34 xaa
    -rw-r--r--. 1 root root   5120 Nov 11 23:34 xab
    -rw-r--r--. 1 root root     290 Nov 11 23:34 xac

/> rm -f x*                         #删除拆分后的小文件
/> split -d -b 5k test.tar.bz2 #-d选项以后缀为数字的形式命名拆分后的小文件
/> ls -l
    -rw-r--r--. 1 root root 10530 Nov 11 23:08 test.tar.bz2
    -rw-r--r--. 1 root root   5120 Nov 11 23:36 x00
    -rw-r--r--. 1 root root   5120 Nov 11 23:36 x01
    -rw-r--r--. 1 root root     290 Nov 11 23:36 x02

/> wc install.log -l             #计算该文件的行数
/> split -l 300 install.log     #每300行拆分成一个小文件
/> ls -l x*
    -rw-r--r--. 1 root root 11184 Nov 11 23:42 xaa
    -rw-r--r--. 1 root root 10805 Nov 11 23:42 xab
    -rw-r--r--. 1 root root 12340 Nov 11 23:42 xac
    -rw-r--r--. 1 root root 11783 Nov 11 23:42 xad
    -rw-r--r--. 1 root root   2105 Nov 11 23:42 xae


★ 文件查找命令find

【find命令的应用示例】
/> ls -l     #列出当前目录下所包含的测试文件
    -rw-r--r--. 1 root root 48217 Nov 12 00:57 install.log
    -rw-r--r--. 1 root root      37 Nov 12 00:56 testfile.dat
    -rw-r--r--. 1 root root 10530 Nov 11 23:08 test.tar.bz2
    -rw-r--r--. 1 root root     183 Nov 11 08:02 users
    -rw-r--r--. 1 root root     279 Nov 11 08:45 users2
    
1. 按文件名查找:
    -name:  查找时文件名大小写敏感。
    -iname: 查找时文件名大小写不敏感。
    #该命令为find命令中最为常用的命令,即从当前目录中查找扩展名为.log的文件。需要说明的是,缺省情况下,find会从指定的目录搜索,并递归的搜索其子目录。
    /> find . -name "*.log"
     ./install.log
    /> find . -iname U*          #如果执行find . -name U*将不会找到匹配的文件
    users users2

2. 按文件时间属性查找:
    -atime  -n[+n]: 找出文件访问时间在n日之内[之外]的文件。
    -ctime  -n[+n]: 找出文件更改时间在n日之内[之外]的文件。
    -mtime -n[+n]: 找出修改数据时间在n日之内[之外]的文件。
    -amin   -n[+n]: 找出文件访问时间在n分钟之内[之外]的文件。
    -cmin   -n[+n]: 找出文件更改时间在n分钟之内[之外]的文件。
    -mmin  -n[+n]: 找出修改数据时间在n分钟之内[之外]的文件。
    /> find -ctime -2        #找出距此时2天之内创建的文件
    .
    ./users2
    ./install.log
    ./testfile.dat
    ./users
    ./test.tar.bz2
    /> find -ctime +2        #找出距此时2天之前创建的文件
    没有找到                     #因为当前目录下所有文件都是2天之内创建的
    /> touch install.log     #手工更新install.log的最后访问时间,以便下面的find命令可以找出该文件
    /> find . -cmin  -3       #找出修改状态时间在3分钟之内的文件。
    install.log

3. 基于找到的文件执行指定的操作:
    -exec: 对匹配的文件执行该参数所给出的shell命令。相应命令的形式为'command' {} \;,注意{}和\;之间的空格,同时两个{}之间没有空格
    -ok:   其主要功能和语法格式与-exec完全相同,唯一的差别是在于该选项更加安全,因为它会在每次执行shell命令之前均予以提示,只有在回答为y的时候,其后的shell命令才会被继续执行。需要说明的是,该选项不适用于自动化脚本,因为该提供可能会挂起整个自动化流程。
    #找出距此时2天之内创建的文件,同时基于find的结果,应用-exec之后的命令,即ls -l,从而可以直接显示出find找到文件的明显列表。
    /> find . -ctime -2 -exec ls -l {} \;
    -rw-r--r--. 1 root root      279 Nov 11 08:45 ./users2
    -rw-r--r--. 1 root root  48217 Nov 12 00:57 ./install.log
    -rw-r--r--. 1 root root        37 Nov 12 00:56 ./testfile.dat
    -rw-r--r--. 1 root root      183 Nov 11 08:02 ./users
    -rw-r--r--. 1 root root  10530 Nov 11 23:08 ./test.tar.bz2
    #找到文件名为*.log, 同时文件数据修改时间距此时为1天之内的文件。如果找到就删除他们。有的时候,这样的写法由于是在找到之后立刻删除,因此存在一定误删除的危险。
    /> ls
    install.log  testfile.dat  test.tar.bz2  users  users2
    /> find . -name "*.log" -mtime -1 -exec rm -f {} \; 
    /> ls
    testfile.dat  test.tar.bz2  users  users2
    在控制台下,为了使上面的命令更加安全,我们可以使用-ok替换-exec,见如下示例:
    />  find . -name "*.dat" -mtime -1 -ok rm -f {} \;
    < rm ... ./testfile.dat > ? y    #对于该提示,如果回答y,找到的*.dat文件将被删除,这一点从下面的ls命令的结果可以看出。
    /> ls
    test.tar.bz2  users  users2

4. 按文件所属的owner和group查找:
    -user:      查找owner属于-user选项后面指定用户的文件。
    ! -user:    查找owner不属于-user选项后面指定用户的文件。
    -group:   查找group属于-group选项后面指定组的文件。
    ! -group: 查找group不属于-group选项后面指定组的文件。
    /> ls -l                            #下面三个文件的owner均为root
    -rw-r--r--. 1 root root 10530 Nov 11 23:08 test.tar.bz2
    -rw-r--r--. 1 root root     183 Nov 11 08:02 users
    -rw-r--r--. 1 root root     279 Nov 11 08:45 users2
    /> chown stephen users   #将users文件的owner从root改为stephen。
    /> ls -l
    -rw-r--r--. 1 root       root 10530 Nov 11 23:08 test.tar.bz2
    -rw-r--r--. 1 stephen root    183 Nov 11 08:02 users
    -rw-r--r--. 1 root       root     279 Nov 11 08:45 users2
    /> find . -user root          #搜索owner是root的文件
    .
    ./users2
    ./test.tar.bz2
    /> find . ! -user root        #搜索owner不是root的文件,注意!和-user之间要有空格。
    ./users
    /> ls -l                            #下面三个文件的所属组均为root
    -rw-r--r--. 1 root      root 10530 Nov 11 23:08 test.tar.bz2
    -rw-r--r--. 1 stephen root    183 Nov 11 08:02 users
    -rw-r--r--. 1 root      root    279 Nov 11 08:45 users2
    /> chgrp stephen users    #将users文件的所属组从root改为stephen
    /> ls -l
    -rw-r--r--. 1 root           root    10530 Nov 11 23:08 test.tar.bz2
    -rw-r--r--. 1 stephen stephen      183 Nov 11 08:02 users
    -rw-r--r--. 1 root            root       279 Nov 11 08:45 users2
    /> find . -group root        #搜索所属组是root的文件
    .
    ./users2
    ./test.tar.bz2
    /> find . ! -group root      #搜索所属组不是root的文件,注意!和-user之间要有空格。    
    ./users

5. 按指定目录深度查找:
    -maxdepth: 后面的参数表示距当前目录指定的深度,其中1表示当前目录,2表示一级子目录,以此类推。在指定该选项后,find只是在找到指定深度后就不在递归其子目录了。下例中的深度为1,表示只是在当前子目录中搜索。如果没有设置该选项,find将递归当前目录下的所有子目录。
    /> mkdir subdir               #创建一个子目录,并在该子目录内创建一个文件
    /> cd subdir
    /> touch testfile
    /> cd ..
    #maxdepth后面的参数表示距当前目录指定的深度,其中1表示当前目录,2表示一级子目录,以此类推。在指定该选项后,find只是在找到指定深度后就不在递归其子目录了。下例中的深度为1,表示只是在当前子目录中搜索。如果没有设置该选项,find将递归当前目录下的所有子目录。
    /> find . -maxdepth 1 -name "*"
    .
    ./users2
    ./subdir
    ./users
    ./test.tar.bz2
    #搜索深度为子一级子目录,这里可以看出子目录下刚刚创建的testfile已经被找到
    /> find . -maxdepth 2 -name "*"  
    .
    ./users2
    ./subdir
    ./subdir/testfile
    ./users
    ./test.tar.bz2
    
6. 排除指定子目录查找:
    -path pathname -prune:   避开指定子目录pathname查找。
    -path expression -prune:  避开表达中指定的一组pathname查找。
    需要说明的是,如果同时使用-depth选项,那么-prune将被find命令忽略。
    #为后面的示例创建需要避开的和不需要避开的子目录,并在这些子目录内均创建符合查找规则的文件。
    /> mkdir DontSearchPath  
    /> cd DontSearchPath
    /> touch datafile1
    /> cd ..
    /> mkdir DoSearchPath
    /> cd DoSearchPath
    /> touch datafile2
    /> cd ..
    /> touch datafile3
    #当前目录下,避开DontSearchPath子目录,搜索所有文件名为datafile*的文件。
    /> find . -path "./DontSearchPath" -prune -o -name "datafile*" -print
    ./DoSearchPath/datafile2
    ./datafile3
    #当前目录下,同时避开DontSearchPath和DoSearchPath两个子目录,搜索所有文件名为datafile*的文件。
    /> find . \( -path "./DontSearchPath" -o -path "./DoSearchPath" \) -prune -o -name "datafile*" -print
    ./datafile3
        
7. 按文件权限属性查找:
    -perm mode:   文件权限正好符合mode(mode为文件权限的八进制表示)。
    -perm +mode: 文件权限部分符合mode。如命令参数为644(-rw-r--r--),那么只要文件权限属性中有任何权限和644重叠,这样的文件均可以被选出。
    -perm -mode:  文件权限完全符合mode。如命令参数为644(-rw-r--r--),当644中指定的权限已经被当前文件完全拥有,同时该文件还拥有额外的权限属性,这样的文件可被选出。
    /> ls -l
    -rw-r--r--. 1 root            root           0 Nov 12 10:02 datafile3
    -rw-r--r--. 1 root            root    10530 Nov 11 23:08 test.tar.bz2
    -rw-r--r--. 1 stephen stephen        183 Nov 11 08:02 users
    -rw-r--r--. 1 root            root        279 Nov 11 08:45 users2
    /> find . -perm 644      #查找所有文件权限正好为644(-rw-r--r--)的文件。
    ./users2
    ./datafile3
    ./users
    ./test.tar.bz2
    /> find . -perm 444      #当前目录下没有文件的权限属于等于444(均为644)。    
    /> find . -perm -444     #644所包含的权限完全覆盖444所表示的权限。
    .
    ./users2
    ./datafile3
    ./users
    ./test.tar.bz2
    /> find . -perm +111    #查找所有可执行的文件,该命令没有找到任何文件。
    /> chmod u+x users     #改变users文件的权限,添加owner的可执行权限,以便于下面的命令可以将其找出。
    /> find . -perm +111     
    .
    ./users    
    
8. 按文件类型查找:
    -type:后面指定文件的类型。
    b - 块设备文件。
    d - 目录。
    c - 字符设备文件。
    p - 管道文件。
    l  - 符号链接文件。
    f  - 普通文件。
    /> mkdir subdir 
    /> find . -type d      #在当前目录下,找出文件类型为目录的文件。
    ./subdir
  /> find . ! -type d    #在当前目录下,找出文件类型不为目录的文件。
    ./users2
    ./datafile3
    ./users
    ./test.tar.bz2
    /> find . -type f       #在当前目录下,找出文件类型为文件的文件
    ./users2
    ./datafile3
    ./users
    ./test.tar.bz2
    
9. 按文件大小查找:
    -size [+/-]100[c/k/M/G]: 表示文件的长度为等于[大于/小于]100块[字节/k/M/G]的文件。
    -empty: 查找空文件。
    /> find . -size +4k -exec ls -l {} \;  #查找文件大小大于4k的文件,同时打印出找到文件的明细
    -rw-r--r--. 1 root root 10530 Nov 11 23:08 ./test.tar.bz2
    /> find . -size -4k -exec ls -l {} \;  #查找文件大小小于4k的文件。
    -rw-r--r--. 1 root            root 279 Nov 11 08:45 ./users2
    -rw-r--r--. 1 root             root    0 Nov 12 10:02 ./datafile3
    -rwxr--r--. 1 stephen stephen 183 Nov 11 08:02 ./users
    /> find . -size 183c -exec ls -l {} \; #查找文件大小等于183字节的文件。
    -rwxr--r--. 1 stephen stephen 183 Nov 11 08:02 ./users
    /> find . -empty  -type f -exec ls -l {} \;
    -rw-r--r--. 1 root root 0 Nov 12 10:02 ./datafile3
    
10. 按更改时间比指定文件新或比文件旧的方式查找:
    -newer file1 ! file2: 查找文件的更改日期比file1新,但是比file2老的文件。
    /> ls -lrt   #以时间顺序(从早到晚)列出当前目录下所有文件的明细列表,以供后面的例子参考。
    -rwxr--r--. 1 stephen stephen   183 Nov 11 08:02 users1
    -rw-r--r--. 1 root           root    279 Nov 11 08:45 users2
    -rw-r--r--. 1 root           root 10530 Nov 11 23:08 test.tar.bz2
    -rw-r--r--. 1 root           root        0 Nov 12 10:02 datafile3
    /> find . -newer users1     #查找文件更改日期比users1新的文件,从上面结果可以看出,其余文件均符合要求。
    ./users2
    ./datafile3
    ./test.tar.bz2
    /> find . ! -newer users2   #查找文件更改日期不比users1新的文件。
    ./users2
    ./users
    #查找文件更改日期比users2新,但是不比test.tar.bz2新的文件。
    /> find . -newer users2 ! -newer test.tar.bz2
    ./test.tar.bz2
   

★xargs命令
该命令的主要功能是从输入中构建和执行shell命令。       
    在使用find命令的-exec选项处理匹配到的文件时, find命令将所有匹配到的文件一起传递给exec执行。但有些系统对能够传递给exec的命令长度有限制,这样在find命令运行几分钟之后,就会出现溢出错误。错误信息通常是“参数列太长”或“参数列溢出”。这就是xargs命令的用处所在,特别是与find命令一起使用。  
    find命令把匹配到的文件传递给xargs命令,而xargs命令每次只获取一部分文件而不是全部,不像-exec选项那样。这样它可以先处理最先获取的一部分文件,然后是下一批,并如此继续下去。  
    在有些系统中,使用-exec选项会为处理每一个匹配到的文件而发起一个相应的进程,并非将匹配到的文件全部作为参数一次执行;这样在有些情况下就会出现进程过多,系统性能下降的问题,因而效率不高;  
    而使用xargs命令则只有一个进程。另外,在使用xargs命令时,究竟是一次获取所有的参数,还是分批取得参数,以及每一次获取参数的数目都会根据该命令的选项及系统内核中相应的可调参数来确定。
/> ls -l
    -rw-r--r--. 1 root root        0 Nov 12 10:02 datafile3
    -rw-r--r--. 1 root root 10530 Nov 11 23:08 test.tar.bz2
    -rwxr--r--. 1 root root    183 Nov 11 08:02 users
    -rw-r--r--. 1 root root    279 Nov 11 08:45 users2
#查找当前目录下的每一个普通文件,然后使用xargs命令来测试它们分别属于哪类文件。
/> find . -type f -print | xargs file 
    ./users2:        ASCII text
    ./datafile3:      empty
    ./users:          ASCII text
    ./test.tar.bz2: bzip2 compressed data, block size = 900k
#回收当前目录下所有普通文件的执行权限。
/> find . -type f -print | xargs chmod a-x
/> ls -l
    -rw-r--r--. 1 root root     0 Nov 12 10:02 datafile3
    -rw-r--r--. 1 root root 10530 Nov 11 23:08 test.tar.bz2
    -rw-r--r--. 1 root root   183 Nov 11 08:02 users
    -rw-r--r--. 1 root root   279 Nov 11 08:45 users2
#在当前目录下查找所有普通文件,并用grep命令在搜索到的文件中查找hostname这个词
/> find . -type f -print | xargs grep "hostname" 
#在整个系统中查找内存信息转储文件(core dump) ,然后把结果保存到/tmp/core.log 文件中。
/> find / -name "core" -print | xargs echo "" >/tmp/core.log  
/> pgrep mysql | xargs kill -9  #直接杀掉mysql的进程
    [1]+  Killed                  mysql

  

posted @ 2019-03-20 10:27  山的那一边  阅读(241)  评论(0)    收藏  举报