find命令的处理动作以及xargs命令
admin
2023-02-25 04:20:10
0

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

处理动作

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

[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以上的文件,并人性化显示其详细信息,那么执行下面的命令就会报错。

[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节介绍)无法实现上面的操作呢?比如我们做下面的测试:

[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" -delete

xargs命令

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

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

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

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

可以发现,虽然通过上面的命令找出了密码,但并没有显示存放该密码的文件名。下面换做用xargs命令来实现该要求,xargs就可以将关键字所在的文件一并显示出来。

[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命令。

相关内容

热门资讯

人民日报刊文:扫码用餐 吃得“... 河南信阳推进公务接待改革扫码用餐 吃得“明白”(厉行节约 反对浪费)本报记者 王乐文 毕京津《人民日...
活动回顾:心灵律动·刚柔共生 心灵律动 - 活动回顾 - “五一”期间, 东莞市工人文化宫连续举办了两场 “心灵律动·刚柔共生”心...
商业航天政策利好 全国首个卫星... 来源:21世纪经济报道 21世纪经济报道记者周慧 5月6日,工业和信息化部官网消息称,工业和信息化部...
伊朗确认前往美国参加世界杯:将... 当地时间5月6日,伊朗国家足球队主教练在接受采访时表示,伊朗国家足球队将于美加墨世界杯开始前14天抵...
雷达、机库、营房、燃料库、飞机... 据《华盛顿邮报》5月6日报道,通过卫星影像分析发现,自2月28日战事爆发以来,伊朗空袭已在中东美军军...
从买买买到租租租,“租用一代”... “五一”假期还在路上,年轻人已经“租”起来了。 “租三天,不到300块钱。”五一放假前一周,清清已给...
【品牌】摩托罗拉大折叠屏新机定... 此前联想预热将于5月19日19点举行联想天禧AI一体多端全场景新品超能之夜活动,届时将带来多款新品,...
常州欣隽益取得接线端子用快速冲... 国家知识产权局信息显示,常州欣隽益科技有限公司取得一项名为“接线端子用快速冲切装置”的专利,授权公告...
美媒:特朗普在结束伊朗战争问题... 据“国会山”网站5月6日报道,周二晚间,美国总统特朗普突然宣布终止旨在打破伊朗对霍尔木兹海峡掌控的军...
和创硅材料取得熔融石英制品擦洗... 国家知识产权局信息显示,东海县和创硅材料有限公司取得一项名为“一种熔融石英制品的擦洗脱泥装置”的专利...