grep 列表中的文件

grep 列表中的文件

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

$ head -n 3 <(cat files.txt)
admin.php
ajax/accept.php
ajax/add_note.php

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

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

$ grep -i 'foo' admin.php
The foo was found

我熟悉国旗-f,它会读到图案从一个文件。但如何阅读输入文件

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

答案1

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

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

给 grep 所有文件。

但是,如果列表中的文件太多,您可能会遇到参数数量问题。在那种情况下我就写

while read filename; do grep -Hi 'foo' "$filename"; done < files.txt

答案2

xargs grep -i -- foo /dev/null < files.txt

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

(unset -v IFS; set -f; grep -i -- foo $(cat files.txt))

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

这些还假设没有任何文件被称为-.

答案3

要从标准输入读取文件名列表,您可以使用xargs.例如,

cat files.txt | xargs -d'\n' grep -i -- 'foo'

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

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

请参阅xargs 手册页以及 xargs 信息页面以获取更多详细信息。

答案4

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

   --arg-file=file
   -a file
          Read items from file instead of standard input.  If you use this
          option, stdin remains unchanged when commands are  run.   Other‐
          wise, stdin is redirected from /dev/null.

所以这也应该有效:

xargs -a files.txt grep -i 'foo'

或文件名中的空格

xargs -d'\n' -a files.txt grep -i 'foo'
xargs -I{} -a files.txt grep -i 'foo' {}

相关内容