列表中的 grep 文件

dot*_*hen 19 grep bash command-substitution process-substitution

我正在尝试针对几百个文件的列表运行 grep:

$ head -n 3 <(cat files.txt)
admin.php
ajax/accept.php
ajax/add_note.php
Run Code Online (Sandbox Code Playgroud)

但是,即使我正在搜索我知道在文件中找到的字符串,以下内容也不会搜索文件:

$ grep -i 'foo' <(cat files.txt)

$ grep -i 'foo' admin.php
The foo was found
Run Code Online (Sandbox Code Playgroud)

我熟悉从文件中-f读取模式的标志。但是如何读取输入文件

我曾考虑过将文件复制到cp似乎支持该<(cat files.txt)格式的临时目录的可怕解决方法,然后从那里 grep 文件。雪莉还有更好的办法。

ori*_*ion 32

您似乎在搜索文件名列表,而不是文件本身。<(cat files.txt)只列出文件。尝试<(cat $(cat files.txt))实际连接它们并将它们作为单个流进行搜索,或者

grep -i 'foo' $(cat files.txt)
Run Code Online (Sandbox Code Playgroud)

给 grep 所有文件。

但是,如果列表中的文件过多,则参数数量可能会出现问题。在那种情况下,我只会写

while read filename; do grep -Hi 'foo' "$filename"; done < files.txt
Run Code Online (Sandbox Code Playgroud)


Sté*_*las 9

xargs grep -i -- foo /dev/null < files.txt
Run Code Online (Sandbox Code Playgroud)

假设文件为空白或换行符分隔(其中引号或反斜杠可用于转义这些分隔符)。使用 GNU,xargs您可以指定分隔符-d(尽管它会禁用引用处理)。

(unset -v IFS; set -f; grep -i -- foo $(cat files.txt))
Run Code Online (Sandbox Code Playgroud)

假设文件是​​空格、制表符或换行符分隔的(尽管您可以通过将其分配给 来选择不同的分隔符,但无法转义这些文件IFS)。如果大多数系统上的文件列表太大,那将失败。

那些还假设没有任何文件被调用-


PM *_*ing 8

要从 stdin 读取文件名列表,您可以使用xargs. 例如,

cat files.txt | xargs -d'\n' grep -i -- 'foo'
Run Code Online (Sandbox Code Playgroud)

默认情况下,xargs从标准输入读取项目,以空格分隔。该-d'\n'告诉它使用换行符作为参数分隔符,所以它可以处理包含空格的文件名。(正如 Stéphane Chazelas 指出的那样,这是一个 GNU 扩展)。但是,它不会处理包含换行符的文件名;我们需要一个稍微复杂的方法来处理这些。

FWIW,这种方法比while read循环要快一些,因为 bash 的read命令非常慢 - 它逐个字符地读取其数据,而xargs更有效地读取其输入。此外,xargsgrep根据需要多次调用命令,每次调用接收多个文件名,这比grep单独调用每个文件名更有效。

有关更多详细信息,请参阅xargs 手册页和 xargs 信息页。


Xen*_*050 5

xargs可以从文件中读取项目(例如您的files.txt列表)中读取项目:

\n\n
   --arg-file=file\n   -a file\n          Read items from file instead of standard input.  If you use this\n          option, stdin remains unchanged when commands are  run.   Other\xe2\x80\x90\n          wise, stdin is redirected from /dev/null.\n
Run Code Online (Sandbox Code Playgroud)\n\n

所以这也应该有效:

\n\n
xargs -a files.txt grep -i 'foo'\n
Run Code Online (Sandbox Code Playgroud)\n\n

或文件名中的空格

\n\n
xargs -d'\\n' -a files.txt grep -i 'foo'\nxargs -I{} -a files.txt grep -i 'foo' {}\n
Run Code Online (Sandbox Code Playgroud)\n