Alp*_*ega 34 command-line grep xargs
我知道该grep
命令并且正在了解 的功能xargs
,因此我通读了此页面,其中提供了一些有关如何使用该xargs
命令的示例。
我对最后一个示例感到困惑,示例 10。它说“xargs 命令执行 grep 命令以查找包含字符串 'stdlib.h' 的所有文件(在 find 命令提供的文件中)”
$ find . -name '*.c' | xargs grep 'stdlib.h'
./tgsthreads.c:#include
./valgrind.c:#include
./direntry.c:#include
./xvirus.c:#include
./temp.c:#include
...
...
...
Run Code Online (Sandbox Code Playgroud)
但是,简单地使用有什么区别
$ find . -name '*.c' | grep 'stdlib.h'
Run Code Online (Sandbox Code Playgroud)
?
显然,我仍在为 xargs 正在做什么而苦苦挣扎,因此感谢您提供任何帮助!
Zan*_*nna 38
$ find . -name '*.c' | grep 'stdlib.h'
Run Code Online (Sandbox Code Playgroud)
这将输出 (stdout)* 从find
到 (stdin of)*grep 'stdlib.h'
作为文本进行管道传输(即文件名被视为文本)。grep
执行其通常的操作并在此文本中找到匹配的行(本身包含该模式的任何文件名)。永远不会读取文件的内容。
$ find . -name '*.c' | xargs grep 'stdlib.h'
Run Code Online (Sandbox Code Playgroud)
这构造了一个命令 grep 'stdlib.h'
,其中的每个结果find
都是一个参数 - 因此这将在由find
(xargs
可以将其标准输入转换为给定命令的参数)找到的每个文件中查找匹配项*
使用-type f
在你的find命令,否则你会从得到错误grep
的匹配目录。此外,如果文件名有空格,xargs
会严重搞砸,所以通过添加-print0
和使用空分隔符来xargs -0
获得更可靠的结果:
find . -type f -name '*.c' -print0 | xargs -0 grep 'stdlib.h'
Run Code Online (Sandbox Code Playgroud)
*添加了@cat评论中建议的这些额外的解释点
xargs 接受其标准输入并将其转换为命令行参数。
find . -name '*.c' | xargs grep 'stdlib.h'
非常类似于
grep 'stdlib.h' $(find . -name '*.c') # UNSAFE, DON'T USE
Run Code Online (Sandbox Code Playgroud)
只要文件名列表对于单个命令行来说不是太长,就会给出相同的结果。(Linux 在单个命令行上支持兆字节的文本,因此通常不需要 xargs。)
但是这两个都很糟糕,因为如果您的文件名包含空格,它们就会中断。相反,find -print0 | xargs -0
有效,但也是如此
find . -name '*.c' -exec grep 'stdlib.h' {} +
Run Code Online (Sandbox Code Playgroud)
这永远不会在任何地方管道文件名:将find
它们批处理成一个大命令行并grep
直接运行。
\;
而不是+
为每个文件单独运行 grep ,这要慢得多。不要那样做。但它+
是一个 GNU 扩展,所以xargs
如果你不能假设 GNU 找到,你需要有效地做到这一点。
如果你省略xargs
,find | grep
它的模式是否与find
打印的文件名列表匹配。
所以在这一点上,你不妨这样做find -name stdlib.h
。当然,使用-name '*.c' -name stdlib.h
,您不会得到任何输出,因为这些模式不能同时匹配,并且 find 的默认行为是将规则和规则放在一起。
less
在过程中的任何一点进行替换,以查看管道的任何部分产生什么输出。
进一步阅读:http : //mywiki.wooledge.org/BashFAQ有一些很棒的东西。
通常,xargs
用于将|
某些命令(带有符号)从一个命令传送到另一个命令 ( Command1 | Command2
),但第一个命令的输出未正确接收为第二个命令的输入的情况。
这通常发生在第二个命令没有正确处理通过标准输入 (stdin) 输入的数据时(例如:多行作为输入、行的设置方式、用作输入的字符、作为输入的多个参数、接收的数据类型为输入等)。给你一个简单的例子,测试以下内容:
示例 1:
ls | echo
- 这不会做任何事情,因为echo
不知道如何处理他收到的输入。现在在这种情况下,如果我们使用xargs
它,它将以一种可以正确处理的方式处理输入echo
(例如:作为单行信息)
ls | xargs echo
- 这将ls
在一行中输出所有信息
示例 2:
假设我在名为 go 的文件夹中有多个 goLang 文件。我会用这样的东西来寻找它们:
find go -name *.go -type f | echo
- 但是如果管道符号在那里和echo
末尾,它就行不通了。
find go -name *.go -type f | xargs echo
- 在这里它会起作用,xargs
但如果我想find
在一行中来自命令的每个响应,我将执行以下操作:
find go -name *.go -type f | xargs -0 echo
- 在这种情况下,来自 的相同输出find
将显示为echo
。
cp, echo, rm, less
需要更好的方式来处理输入的命令和其他命令在与xargs
.