有没有更简单的方法来grep目录下的所有文件?

Dan*_*umb 21 grep find

当我想在整个树中搜索某些内容时,我使用

find . -type f -print0 | xargs -0 grep <search_string>
Run Code Online (Sandbox Code Playgroud)

在性能或简洁方面有没有更好的方法来做到这一点?

Phi*_*pos 43

检查您的grep支持-r选项(对于recurse):

grep -r <search_string> .
Run Code Online (Sandbox Code Playgroud)


Kus*_*nda 12

如果你想递归到子目录:

grep -R 'pattern' .
Run Code Online (Sandbox Code Playgroud)

-R选项不是标准选项,但大多数常见grep实现都支持。

  • 当涉及 GNU grep 时,使用 `-r` 而不是 `-R` 来跳过符号链接 (7认同)
  • @Kusalananda 递归?我认为,尽管当前的 GNU `grep` 实现会捕获递归。否则,这取决于您所说的“树”是什么意思。 (4认同)
  • @Kusalananda 如果系统提供了循环?永远不会迷失在`/sys/devices/cpu/subsystem/devices/cpu/subsystem/devices/cpu/...`(-XI 就像照顾我的工具(除非他们提供了他们称之为“AI”的奇怪魔法)。(- ; (3认同)
  • @Philippos 恕我直言,照顾用户不是像`grep`这样的工具应该做的事情。如果用户在他们的目录结构中有符号链接循环,那是用户的问题:-) (2认同)

Pie*_*ume 12

一个子最佳答案:不是管道的输出findgrep,你可以只运行

find . -type f -exec grep 'research' {} '+'
Run Code Online (Sandbox Code Playgroud)

瞧,一个命令而不是两个命令!

解释 :

find . -type f
Run Code Online (Sandbox Code Playgroud)

在 .

-exec grep 'research'
Run Code Online (Sandbox Code Playgroud)

grep '研究'

{}
Run Code Online (Sandbox Code Playgroud)

在找到的文件名中

'+'
Run Code Online (Sandbox Code Playgroud)

每个文件名使用一个命令,而不是每个文件名一次。

Nb:';'每个文件名都会有一次。

除此之外,如果您使用它来处理源代码,您可以查看ack,它是为轻松查找代码位而设计的。

确认

编辑 :

你可以稍微扩展一下这项研究。首先,您可以使用 的-name ''开关find来查找具有特定命名模式的文件。

例如 :

  • 只有对应于日志的文件: -name '*.log'

  • 只有对应于 c 头文件的文件,但你不能坚持使用大写或小写作为你的文件扩展名: -iname *.c

Nb :像 forgrepack-i在这种情况下开关意味着不区分大小写。

在这种情况下,grep 将显示没有颜色和行号。

您可以使用--color-n开关(分别在文件中的颜色和行号)进行更改。

最后,你可以有类似的东西:

find . -name '*.log' -type f -exec grep --color -n 'pattern' {} '+'
Run Code Online (Sandbox Code Playgroud)

例如

$ find . -name '*.c' -type f -exec grep -n 'hello' {} '+' 
./test2/target.c:1:hello
Run Code Online (Sandbox Code Playgroud)

  • `ack` 很棒,而更快的 `ack` 版本是 `ag`(银色搜索器,https://geoff.greer.fm/ag/) (5认同)

Pet*_*tro 5

如上所述-r-R(取决于所需的符号链接处理)是一个快速选项。

但是-d <action>,有时可能很有用。

好的地方-d是跳过命令,当您只想扫描当前级别时,它会使“grep: directory_name: Is a directory”静音。

$ grep foo * 
grep: q2: Is a directory 
grep: rt: Is a directory 

$ grep -d skip foo *  
$ 
Run Code Online (Sandbox Code Playgroud)

而且当然:

$ grep -d recurse foo * 
(list of results that don't exist because the word foo isn't in our source code
and I wouldn't publish it anyway).  
$ 
Run Code Online (Sandbox Code Playgroud)

-d skip选项在另一个脚本中非常方便,因此您不必2> /dev/null. :)