如何将文件列表传递给 grep

Hea*_*ray 121 grep pipe find

我正在使用find并获取我想要grep通过的文件列表。我如何通过管道将该列表传递给grep

Mic*_*zek 155

嗯,适用于写入 stdout 的任何命令的一般情况是 use xargs,它可以让您将任意数量的命令行参数附加到命令的末尾:

$ find … | xargs grep 'search'
Run Code Online (Sandbox Code Playgroud)

或者grep使用反引号或将命令嵌入到您的行中$(),这将运行命令并替换其输出:

$ grep 'search' $(find …)
Run Code Online (Sandbox Code Playgroud)

请注意,如果文件名包含空格或某些其他“奇怪的字符”(\'"对于 xargs,\[*?对于$(find …)),这些命令将不起作用。


但是,在特定情况下,find内置了对给定参数执行程序的能力:

$ find … -exec grep 'search' {} \;
Run Code Online (Sandbox Code Playgroud)

-exec和之间的一切都是;要执行的命令;{}替换为由 找到的文件名find。这将为grep每个文件单独执行;由于grep可以使用许多文件名并全部搜索它们,因此您可以更改;to+以告诉 find 一次将所有匹配的文件名传递给grep

$ find … -exec grep 'search' {} \+
Run Code Online (Sandbox Code Playgroud)

  • 我建议使用`-exec`,而不是`xargs`。如果你在 [`find`](http://www.folkstalk.com/2011/12/101-examples-of-using-find-command-in.html) 中使用 `-exec`,它只会创建一个 shell 到 [grep](http://www.folkstalk.com/2011/12/101-examples-of-using-find-command-in.html) 的内容。如果你使用`xargs`,它会创建两个shell:一个用于`find`,另一个用于`xargs`。 (4认同)
  • 应注意前两种形式不适用于包含空格的文件名。 (2认同)
  • 我更喜欢`find ... -type f -print0 | xargs -r0 grep '搜索' /dev/null`。量子电子器件。虽然 `-exec +` 非常高效,但它并不存在于所有版本的 find 上。 (2认同)
  • 通过实验,我发现 `$ find ... -exec grep 'search' {} \+` 形式是*快的*。 (2认同)

Gil*_*il' 10

某些版本grep(例如在非嵌入式 Linux 或BSD或 Mac OS X 上)具有-r进行递归搜索的选项。在 OpenBSD 上,使用-R(并且--exclude在下面的示例中没有)。这涵盖了findwith 的简单组合grep

如果您的实现没有-R标志,或者如果您想要更高级的文件匹配条件,您可以使用-exec主要 offind使其执行grep。一些较旧的find实现不支持-exec+;在这些系统上,使用 a;而不是 the +(这将对grep每个文件调用一次,因此速度会更慢,否则结果将相同)。请注意即使碰巧在单个文件上调用它也会显示文件名的/dev/null技巧grep(GNU grep 和 FreeBSD/NetBSD/OSX grep 有一个-H选项可以实现相同的效果)。

find . -type f -name '*.o' -prune -o -exec grep 'needle' /dev/null {} +
grep -r --exclude='*.o' 'needle' .
Run Code Online (Sandbox Code Playgroud)

  • `GNU grep` 有 `-H` 选项来始终打印文件名。 (3认同)