性能@garyjohn

性能@garyjohn

为什么我不能使用 grep find?只有 greping cat 或 find 才有用。据我所知,grep 程序可以看到每个命令运行的上下文。但对于像我这样的新手来说,这是违反直觉的。当使用参数时,grep 可以搜索文件,但当使用管道 ( | ) 时,它就不能。

答案1

find命令生成符合搜索条件的路径名列表,在本例中为带扩展名的名称.ebuild。(但有一个小问题:您需要在通配符周围加上引号,这样 shell 就会将其传递给 find 而不先尝试扩展它。)如果您将其输入到grep,您所做的只是过滤该名称列表,而不是这些文件的内容。

相比之下,cat $(find ...)构造使用命令替换(这是其中的$(...)一部分)将 find 的输出(它生成的路径名列表)粘贴回到命令行作为 的参数cat,从而将cat这些文件的内容写入 stdout 和grep

做你想做的事情的更简单的方法是使用命令替换将名称grep直接传递给:

grep RESTRICT $(find /usr/portage -name "e.build")

答案2

为了以更简洁的形式表达 Nicole Hamilton 的命令,您可以将 -exec 标志用于 find 命令。

find /usr/portage -name '*.ebuild' -exec grep RESTRICT {} \;

这会将匹配文件的名称传递给 grep,其中花括号被文件名替换。'\;' 是转义的 ';',用于表示命令的结束。

性能@garyjohn

这是运行 find 命令的不同时间的比较。所有这些测试都是针对 portage 的最新快照执行的(http://distfiles.gentoo.org/snapshots/portage-latest.tar.bz2)。在计时这些测试之前,我运行了“find .”和“grep -Rni . .”,因此我希望磁盘和 RAM 缓存在所有测试中都应该相似。

以下是两个命令的时序:

% time grep RESTRICT $(find . -name "*.ebuild") > /dev/null
grep --color RESTRICT $(find . -name "*.ebuild") > /dev/null  0.05s user 0.13s system 95% cpu 0.192 total

% time find . -name "*.ebuild" -exec grep RESTRICT {} \; > /dev/null
find . -name "*.ebuild" -exec grep RESTRICT {} \; > /dev/null  0.68s user 2.63s system 14% cpu 22.523 total

正如您所看到的,cat 方法比我的示例速度更快,仅花费了大约 5% 的时间。

但是,如果 find 命令返回的文件过多,我们将遇到 shell 对单个命令长度的限制。这将导致命令失败。

% time grep RESTRICT $(find . -name "*") > /dev/null
zsh: argument list too long: grep
grep --color RESTRICT $(find . -name "*") > /dev/null  0.34s user 0.04s system 99% cpu 0.374 tota

要查看您系统上的这个限制,请使用。

getconf ARG_MAX

以下是使用相同 glob 运行的 find。请注意,它需要很长时间才能完成,但它确实成功退出。

% time find . -name "*" -exec grep RESTRICT {} \; > /dev/null    
find . -name "*" -exec grep RESTRICT {} \; > /dev/null  2.52s user 11.00s system 12% cpu 1:47.67 total

安全运行此命令的最佳方法是使用 xargs。

% time find . -name "*" -print0 | xargs -0 grep RESTRICT > /dev/null 
find . -name "*" -print0  0.16s user 0.29s system 51% cpu 0.886 total
xargs -0 grep RESTRICT > /dev/null  0.33s user 0.59s system 100% cpu 0.915 total

使用 xargs 可以在不到 2 秒的时间内通过 grep 查找整个 portage 树 (~159995 个文件,724M)。

相关内容