grep - 限制读取文件的数量

9
我有一个包含超过10万个文件的目录。我想知道是否存在字符串"str1"作为任何这些文件内容的一部分。
命令:grep -l 'str1' *读取所有文件,所以执行太慢了。
如何让grep在找到匹配项后停止读取其他文件? 有没有一行命令可以实现?
注意:我已经尝试了grep -l 'str1' * | head,但是它的执行时间与上一个命令一样长。

这个命令在文件数量较少的目录中能否起作用? - Roman Susi
也许已经在这里得到了答案:https://dev59.com/wWYq5IYBdhLWcg3w7EwF - Roman Susi
head -1 这个命令就可以解决。 - Roman Susi
3
也许是因为全局搜索在处理大量文件时速度很慢。你可以尝试使用 find path/to/directory/ -type f -exec grep -l 'str1' /dev/null {} + 命令来代替。 - gniourf_gniourf
1
考虑在搜索固定字符串时使用 fgrep 代替 grep - Zlemini
显示剩余2条评论
2个回答

6
命令参数中命名10万个文件名会导致问题。这可能超出了Shell命令行的大小限制。
但是,如果您使用递归选项,并只使用包含文件的目录名称(如果您想要在当前目录中搜索文件,则为),则无需命名所有文件:
grep -l -r 'str1' . | head -1

2
@gniourf_gniourf,OP的问题标记为[tag:linux],所以我认为可以安全地假设他们正在使用GNU grep。 - Bill Karwin
好的,没问题... ;) - gniourf_gniourf
grep -m 1 -l -e 'str1' * | head -1 print the error: -bash: /bin/grep: Argument list too long - dev4life
2
@user2070775:这就是为什么Bill建议使用grep -r而不是glob(这也是我在评论中建议使用find的原因)。 - gniourf_gniourf
4
@bishop,我没有包含“-m 1”,因为它是多余的,因为“-l”在找到第一个匹配项后停止读取文件。 - Bill Karwin
显示剩余5条评论

3

使用grep -m 1命令,以便在文件中找到第一个匹配项后停止搜索。对于大型文本文件非常高效。

grep -m 1 str1 * /dev/null | head -1

如果只有一个文件,那么上面的 /dev/null 确保 grep 在输出中打印出文件名。 如果你想在任何文件中找到第一个匹配项后停止:
for file in *; do
  if grep -q -m 1 str1 "$file"; then
    echo "$file"
    break
  fi
done
< p > for循环在处理包含大量文件的目录时,还可以避免参数过多的问题。


1
请注意,OP已经使用了-l,这使得grep在第一次匹配后停止。 - gniourf_gniourf
1
for file in *永远不会遭受“参数过多”的问题,这是一种解决方法。例如,请参见此处:http://www.in-ulm.de/~mascheck/various/argmax/ - Benjamin W.
@BenjaminW. - 谢谢!我之前不知道这个。我已经相应地编辑了我的回答。 - codeforester
1
在shell中对for file in *的特殊处理是一件新事物(或许某些时候是这样)。过去(20世纪90年代),许多不同的shell在扩展shell内置项时都存在很多错误和溢出问题。因此,除非您 确切知道 只有这种方式才能工作的shell,否则不要依赖它。 - Zan Lynx
1
@gniourf_gniourf 好的 - 但是在我的系统上,使用进程替换和 findwhile 方法甚至更慢。我只是指出,在 for 循环中不需要解决 "参数列表过长" 的问题(而 @ZanLynx 的评论告诉我这并不总是正确的)。 - Benjamin W.
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接