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


21

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

find . -type f -print0 | xargs -0 grep <search_string>

在性能或简洁性方面,有更好的方法吗?


2
@Downvoter:如果您可以分享您的问题,很高兴改进此问题。
Dancrumb

2
许多查找版本都有内置的xargs:find。-type f -exec fgrep <search_string> {} +
simpleuser

Answers:


42

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

grep -r <search_string> .

1
是的...我刚刚找到stackoverflow.com/questions/16956810/…这也是答案。
Dancrumb

添加一个关于--exclude-dir性能的评论,我们有一个赢家!
Dancrumb

1
请注意,它不是可移植的,但是grep在最近的FreeBSD和Linux发行版中都支持它。又为什么--exclude-dir呢?您不是要搜寻整棵树吗?
Philippos

公平点... --exclude-dir实际上在我的用例中很方便(因为子树的部分很大,但是没用),我确实询问过性能...但是您说得对,这不是必需的。
Dancrumb

在这种情况下,我必须补充说,IIRC --exclude-dir是GNU专有的grep。(-:
Philippos

13

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

find . -type f -exec grep 'research' {} '+'

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

说明:

find . -type f

在中找到所有常规文件。

-exec grep 'research'

grep“研究”

{}

在找到的文件名中

'+'

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

Nb:';'它将是每个文件名一次。

除此之外,如果您使用它来处理源代码,则可以查看ack,它旨在轻松查找代码位。

确认

编辑:

您可以扩大研究范围。首先,您可以使用的-name ''开关find查找具有指定命名模式的文件。

例如 :

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

  • 仅对应于c标头的文件,但文件名扩展名不能使用大写或小写: -iname *.c

Nb:grep和和一样ack,此-i开关表示不区分大小写。

在这种情况下,grep将显示为无颜色且无行号。

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

最后,您可以看到类似:

find . -name '*.log' -type f -exec grep --color -n 'pattern' {} '+'

例如

$ find . -name '*.c' -type f -exec grep -n 'hello' {} '+' 
./test2/target.c:1:hello

5
ack是伟大的,更快的版本的ackIS ag(银搜索,geoff.greer.fm/ag
cfeduke

1
我更喜欢使用-name '*.log'它更快的过滤器。
sdkks

@cfeduke我还没有尝试过,主要是因为ag不是WSL上默认apt仓库的一部分(您必须使用已有的内容!)
Pierre-Antoine Guillaume

一个技巧是在grep中添加/ dev / null以显示文件名。
ChuckCottrill

一个技巧是仅搜索目录,然后-exec grep / dev / null {} / *以每个目录使用单个fork / exec来获取所有文件。
ChuckCottrill

12

如果要递归到子目录:

grep -R 'pattern' .

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


7
使用-r,而不是-R跳过时,GNU的grep而言符号链接
αғsнιη

1
@AFSHIN为什么您不想跟随符号链接?
库萨兰达

4
@Kusalananda递归?grep我认为,尽管当前的GNU 实现捕获了递归。否则,这取决于您所说的“树”的含义。
Philippos

2
@Philippos恕我直言,保姆用户不是工具之类的grep事情。如果用户的目录结构中存在符号链接循环,那么这就是用户的问题:-)
库萨兰达

3
@Kusalananda如果系统提供了循环?永远不会迷失/sys/devices/cpu/subsystem/devices/cpu/subsystem/devices/cpu/...(像XI这样的工具会照顾我(除非它们提供被称为“ AI”的怪异魔术)。)(-;
Philippos

5

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

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

一件好事-d是skip命令,当您只想扫描当前级别时,它将使“ grep:directory_name:是目录”静音。

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

$ grep -d skip foo *  
$ 

而且当然:

$ 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).  
$ 

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


0

如果要处理大量文件,则如果您修剪需要搜索的文件而不是grep子文件夹中的所有文件,则grep的运行速度会更快。

我有时会使用这种格式:

grep "primary" `find . | grep cpp$`

.结尾的子文件夹中找到所有文件cpp。然后grep这些文件为“主要”。

如果需要,可以继续将这些结果传递给进一步的grep调用:

grep "primary" `find . | grep cpp$` | grep -v "ignoreThis" | grep -i "caseInsensitiveGrep"

1
背景知识不是现代的好习惯,它们几乎已经过时了
Christopher

1
如果您的文件名中带有特殊字符,则此操作将中断。我不知道它们必须具有多么特殊才能使它按原样工作,但是您要做的实际上与解析ls的输出几乎相同,这也是不好的。
简历
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.