转自于:http://fatmouse.xyz/2016/05/10/2016-05-10-find-grep-xargs-and-pipe/python
相信你们都知道在目录中搜索含有固定字符串文件的命令:fetch
1 |
find . -name '*.py' |xargs grep test |
刚开始的时候,我不熟悉xargs
命令,因此直接使用的命令是spa
1 |
find . -name '*.py' |grep test |
结果并非本身所指望的。此命令只是找出文件名*.txt
有test
的状况。code
这里我就研究一下,究竟xargs
作了什么,使得结果不相同。ip
这两个词咱们在Linux命令中是很常见的。可是参数和标准输入实际上是有区别的。咱们平常使用的不少命令,例如ls -lah .
中。l
, a
, h
,.
都是命令ls
的参数。至于标准输入,能够说它某种流数据。而一般来说标准输入的流数据来源就是咱们的终端输入。在Linux命令中,有些命令能够接收标准输入,有些是不能的。像上面的ls
,就是只能接收参数,不能接收标准输入。像cat
命令或echo
命令,这些是能够的。字符串
怎么分辨一个命令可不能够接收标准输入?很简单,当你敲完命令回车后,终端会等待接收你的输入,例如当你在终端输入cat
后,终端会等待你输入字符,当你输入一些字符后,而后按Ctrl-C
发送终止符号。这时cat
命令接收标准输入完毕,执行命令,也就是将刚才键入的内容输出的标准输出上(屏幕)。input
管道的做用是将前面命令的标准输出做为后面命令的标准输入。这里要注意,后面的命令接收的是标准输入,因此若是命令不支持接收标准输入,那么就不能直接使用管道,例如经常使用的ls
命令,只能使用参数,而不能使用标准输入,因此[command] | ls
是不能使用的。而命令如echo
或cat
就能够。那么确定有方法来实现这些不能使用标准输入的命令与管道结合,这时候xargs
便出场了。it
xargs
命令通俗来说就是将标准输入转成各类格式化的参数,因此命令[command 1] | xargs [command 2]
就是将command 1
的标准输出结果,经过管道|
变成xargs
的标准输入,而后xargs
再将此标准输入变成参数,传给[command 2]
。这样一来,经过xargs
命令,咱们即可以在管道后面使用那些不接收标准输入的命令了。例如[command 1]|xargs ls
,是否是很熟悉?pip
有了以上的知识点,到这里终于能够解答最开始的问题了。为何命令table
1 |
find . -name '*.py' |grep test |
和
1 |
find . -name '*.py' |xargs grep test |
的结果是不同的了。
咱们首先来查看grep手册。经过man grep
命令。
1 |
DESCRIPTION |
这里能够看到grep是支持标准输入的。
假设目录存在以下文件:
1 |
$ ls |
那么对于第一个命令find . -name '*.py' |grep test
,是将前面命令的标准输出做为标准输入传给了grep test
,那么grep
是从这些标准输入寻找test
字符,也就是文件名组成的字符流
1 |
$ find . -name '*.py' |grep test |
能够看到最终选择出的是这些文件名。
而对于第二个命令find . -name '*.py' |xargs grep test
,经过xargs
,find
获得的文件名成为了参数传给后面的grep
,那么这时候这些文件名就是实实在在的文件标识,grep
接收后会按正常的使用方式在各文件中搜寻字符串。
1 |
#find . -name '*.py' |xargs grep test |
到这里算是将find
,grep
,xargs
和管道的做用理解清楚了。
xargs
还有指定参数位置的做用。假设咱们要将目录下全部的.py
文件放到Python目录中去,能够使用命令find . -name '*.py' | xargs -I {} mv {} ./Python
参数-I
指定了管道前命令做为参数所应该在管道后面命令的位置。咱们在查看不少命令手册时,手册会说明命令的使用方法。例如
grep [OPTIONS] PATTERN [FILE...]
,也就是命令的最后一个位置是文件名[FILE]。
这里要注意这个文件名[FILE]也是参数。