“xargs grep”有什么作用?

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评论中建议的这些额外的解释点

  • 您可能会考虑注意(因为您似乎省略了)`|` 将 **stdout** 管道输送到 grep 的 **stdin** 的关键点,这与 grep 的参数不同并给出了令人困惑的结果。 (2认同)

Pet*_*des 7

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 找到,你需要有效地做到这一点。


如果你省略xargsfind | grep它的模式是否与find打印的文件名列表匹配。

所以在这一点上,你不妨这样做find -name stdlib.h。当然,使用-name '*.c' -name stdlib.h,您不会得到任何输出,因为这些模式不能同时匹配,并且 find 的默认行为是将规则和规则放在一起。

less在过程中的任何一点进行替换,以查看管道的任何部分产生什么输出。


进一步阅读:http : //mywiki.wooledge.org/BashFAQ有一些很棒的东西。


Lui*_*ado 5

通常,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.