如何将文件列表传递给grep


98

我正在使用find并获取要grep浏览的文件列表。如何将该列表发送到grep

Answers:


116

好吧,与写到stdout的任何命令一起使用的通用情况是use xargs,它将使您可以将任意数量的命令行参数附加到命令的末尾:

$ find … | xargs grep 'search'

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

$ grep 'search' $(find …)

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


但是,在特定情况下,find可以根据给定参数执行程序是内置的:

$ find … -exec grep 'search' {} \;

-exec和之间的所有内容都是;要执行的命令;{}被替换为的文件名find。这将为grep每个文件单独执行;因为grep可以有许多的文件名和搜索所有这些,你可以改变;,以+告诉找到所有的匹配文件名传递给grep一次:

$ find … -exec grep 'search' {} \+

1
应该注意的是,前两种形式不适用于包含空格的文件名。
enzotib 2011年

1
我更喜欢find ... -type f -print0 | xargs -r0 grep 'search' /dev/null。QED。虽然-exec +非常有效,但并非所有版本的find都存在。
Arcege 2011年

遗憾的是我无法检查您正确的3次。
Arcabard 2011年

3
我建议使用-exec而不是xargs。如果使用-execin find,它将仅创建一个外壳来grep内容。如果使用xargs,它将创建两个shell:一个用于find,另一个用于xargs

2
通过实验我发现,$ find … -exec grep 'search' {} \+形式是是最快的。
gogoud

9

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

如果您的实现没有该-R标志,或者您希望使用更高级的文件匹配条件,则可以使用的-exec主要值find使其执行grep。一些较旧的find实现不支持-exec+;在这些系统上,请使用;而不是+(这将对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' .

2
GNU grep具有-H始终打印文件名的选项。
enzotib 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.