find命令的处理动做以及xargs命令

本身的《Linux系统管理初学者指南--基于CentOS 7.6》已于2019年10月份出版,对于这本书的质量整体上感受还算满意,可是限于当时的知识水平,有些地方描述的仍然不是很清楚,因此在讲课的过程当中也在不断进行修订。好比最近在讲到find命令的处理动做时,很多学生就提出疑问,于是我对原书中这部份内容进行了重写,但愿再版时能够订正。
find命令的处理动做以及xargs命令linux

处理动做

find命令不只能够查找,还能够对找到的结果进行进一步的处理,这就要用到“处理动做”。
例如,找出/usr/bin目录中全部的符号连接文件。
[root@localhost ~]# find /usr/bin -type l
上面这条命令查找出来的结果只显示文件名,若是咱们还想查看每一个符号连接文件都指向了哪一个源文件,就能够在find命令的最后加上处理动做“-ls”。ssh

[root@localhost ~]# find /usr/bin -type l -ls
50346791    0 lrwxrwxrwx   1 root    root  3 2月 14  2019 /usr/bin/captoinfo -> tic

须要注意的是,这个处理动做“-ls”属因而find命令的一部分,而并不是是以前所介绍的ls命令,于是没法在处理动做“-ls”以后加上ls命令的各类选项。例如,咱们但愿找出/etc目录中全部大小在1MB以上的文件,并人性化显示其详细信息,那么执行下面的命令就会报错。ide

[root@localhost ~]# find /etc -size +1M -ls -lh
find: 未知的断言“-lh”

要实现这个需求,就要借助于find命令的另一个处理动做“-exec”。这个处理动做能够将find命令找到的结果看成文件去处理,在“-exec”的后面要跟上进一步处理所要执行的命令,另外在命令中还须要使用符号“{}”表示find命令查找到的结果,在命令的最后必须添加“ \;”表示命令结束(注意前面有个空格)。
例如,找出/etc目录中全部大小在1MB以上的文件,并人性化显示其详细信息,下面这条命令才是正确的作法。在这条命令中,ls就是以前所介绍的ls命令,咱们借助于-exec将find命令找到的结果,以文件的形式传给ls命令继续处理。测试

[root@localhost ~]# find /etc -size +1M -exec ls -lh {} \;
-rw-------. 1 root root 3.8M 11月  3 2018 /etc/selinux/targeted/active/policy.kern

再好比,找出/tmp目录中全部后缀为“.txt”的文件并将其删除。
[root@localhost ~]# find /tmp -name "*.txt" -exec rm -f {} \;
不少同窗在这里会疑惑,为何这里用管道符“|”(将在2.9.5节介绍)没法实现上面的操做呢?好比咱们作下面的测试:code

[root@localhost ~]# touch /tmp/{a,b,c}.txt  #在/tmp目录中生成3个测试文件
[root@localhost ~]# find /tmp -name "*.txt" | rm -f     #利用管道结合rm删除
[root@localhost ~]# find /tmp -name "*.txt"     #测试文件仍然存在
/tmp/a.txt
/tmp/b.txt
/tmp/c.txt
[root@localhost ~]# find /tmp -name "*.txt" -exec rm -f {} \;   #利用exec结合rm删除
[root@localhost ~]# find /tmp -name "*.txt" #测试文件被成功删除

处理动做-exec最主要的做用就是能够将find命令找到的结果当成文件去处理,而默认状况下,find命令找到的结果是被看成文本信息去处理的。
怎样理解上面这段话呢?好比对于执行“find /tmp -name "*.txt"”命令所找到的三个文件:/tmp/a.txt、/tmp/b.txt、/tmp/c.txt,默认状况下find命令只是把符合查找条件的这三个文件找到,并把它们的名字在屏幕上输出,于是咱们在屏幕上所看到的只是三行文本信息。对于文本信息,可使用以前介绍的文件内容操做命令进行处理,好比用wc命令统计行数,用grep命令进行过滤等。对象

[root@localhost ~]# find /tmp -name "*.txt" | wc -l     #统计find找到的文件数量
3
[root@localhost ~]# find /tmp -name "*.txt" | grep 'a'  #对find的结果进行过滤
/tmp/a.txt

对于文本信息,以前介绍的文件和目录操做命令就没法处理了,好比cp、mv、rm等,由于这些命令所操做的对象必须是文件。此时-exec就能够派上用场,由于它的主要做用就是能够将find命令找到的结果再也不看做是文本信息,而是看做文件。于是若是须要对find的结果用文件操做命令进行进一步处理的话,那么就须要结合-exec。
例如,查找/boot目录下的以“init”开头的文件,并将其复制到/tmp目录。
[root@localhost ~]# find /boot -name "init*" -exec cp {} /tmp \;
除了-ls和-exec以外,还有一个比较经常使用的处理动做是-delete,它能够将find找到的结果直接删除。
例如以前的操做:找出/tmp目录中全部后缀为“.txt”的文件并将其删除。其实更为简便的作法是下面的命令:
[root@localhost ~]# find /tmp -name "*.txt" -deleteblog

xargs命令

当在find命令中利用-exec对查找到的结果进行进一步处理时,有时可能会出现问题。这是由于-exec是将find所找到的结果一次性地送给后面的命令进行处理,有时候find可能会找到大量的文件,超出了后面的命令所能处理的参数范围,这时就会出现溢出错误,错误信息一般是“参数列太长”或“参数列溢出”,这时就可使用xargs命令。xargs虽然自己是一个独立的Linux命令,但一般都是被用来配合find命令使用。经过xargs,能够将find所找到的结果分批次地送给以后的命令进行处理,从而避免出现溢出问题。
xargs命令须要经过管道与find命令配合使用,xargs的命令格式“find ……| xargs commands”。
下面咱们先准备一个测试文件。get

[root@localhost ~]# mkdir /tmp/pass
[root@localhost ~]# echo "password:123" >> /tmp/pass/test.txt

假设在/tmp目录中存放了大量的文件,在其中的某个文件里存放了一个密码,关键字为“password”,咱们如今但愿可以将这个存放了密码的文件找出来。
若是利用find命令的-exec选项,能够执行下面的命令:it

[root@localhost ~]# find /tmp -type f -exec grep "password" {} \;
password:123

能够发现,虽然经过上面的命令找出了密码,但并无显示存放该密码的文件名。下面换作用xargs命令来实现该要求,xargs就能够将关键字所在的文件一并显示出来。class

[root@localhost ~]# find /tmp -type f | xargs grep "password"
/tmp/pass/test.txt:password:123

再好比,咱们但愿将/tmp目录以及/tmp全部下级子目录中,文件名以“.txt”做为后缀的文件都复制到/root目录中。若是用find命令的-exec来实现:
[root@localhost ~]# find /tmp -name "*.txt" -exec cp {} /root \;
若是用xargs命令来实现,一样须要用“{}”来代指find命令查找到的结果,而且须要为xargs命令添加-i选项。
[root@localhost ~]# find /tmp -name "*.txt" | xargs -i cp {} /root
经过这几个实例能够发现,xargs命令与find命令-exec处理动做的功能基本相同,因此若是-exec能够知足要求,那么就无需使用xargs命令。xargs命令的主要用途在于它能够对find命令找到的结果分批处理,避免出现溢出错误。
好比在/etc目录中一共有2507个普通文件。

[root@localhost ~]# find /etc -type f | wc -l
2507

若是咱们但愿能找出/etc目录中全部包含关键字“PermitRootLogin”的文件,分别用这两种方法来实现:

[root@localhost ~]# find /etc -type f -exec grep "PermitRootLogin" {} \;
#PermitRootLogin yes
# the setting of "PermitRootLogin without-password".
[root@localhost ~]# find /etc -type f | xargs grep "PermitRootLogin" 
/etc/ssh/sshd_config:#PermitRootLogin yes
/etc/ssh/sshd_config:# the setting of "PermitRootLogin without-password".

能够发如今用-exec的方法实现时,出现了明显的卡顿,若是数据量再大一些的话,可能就会致使溢出。而用xargs命令来实现,一方面更为快速,另外一方面不会出现溢出问题,并且显示的内容也更为详细。因此在进行这类操做时,更加推荐使用xargs命令。

相关文章
相关标签/搜索