如何从grep -R中排除目录?


668

我想遍历除“ node_modules”目录以外的所有子目录。



14
只需键入“ man grep”,您将在其中看到--exclude和--exclude-dir选项-从该问题的标题开始,我假设您已经了解grep ...
arcseldon

34
如果您正在git存储库中查找代码,并且node_modules位于.gitignoregit grep "STUFF"则是最简单的方法。git grep搜索工作树中的跟踪文件,忽略所有内容.gitignore
0xcaff 2016年

2
节点的示例:grep -R --exclude-dir={node_modules,bower_components} "MyString" | cut -c1-"$COLUMNS"-进一步,您始终可以在shell中将此别名化为'nodegrep'或其他名称,并使用命令参数作为字符串输入
。。– bshea

Answers:


394

解决方案1(组合findgrep

该解决方案的目的不是要处理grep性能,而是要显示一个可移植的解决方案:还应该与busybox或2.5之前的GNU版本一起使用。

使用find,排除foo和bar目录:

find /dir \( -name foo -prune \) -o \( -name bar -prune \) -o -name "*.sh" -print

然后结合find使用和grep作为递归解决方案的非递归使用:

find /dir \( -name node_modules -prune \) -o -name "*.sh" -exec grep --color -Hn "your text to find" {} 2>/dev/null \;

解决方案2(递归使用grep):

您已经知道此解决方案,但是我添加了它,因为它是最新,最有效的解决方案。请注意,这是一种不易移植的解决方案,但更易于理解。

grep -R --exclude-dir=node_modules 'some pattern' /path/to/search

要排除多个目录,请--exclude-dir用作:

--exclude-dir={node_modules,dir1,dir2,dir3}

解决方案3(Ag)

如果您经常搜索代码,Ag(银搜索器)是grep的一种更快的选择,它是为搜索代码而定制的。例如,它会自动忽略中列出的文件和目录.gitignore,因此您不必继续将相同的繁琐的排除选项传递给grepfind


2
这个组合的搜索速度比--exclude-dir=dir它显示了其色彩效果-容易阅读
美心叶夫列莫夫

27
“这种结合” find ... -exec并不比grep --exclude-dir我快。(更快地26K +文件的38K +在HDD上过滤掉约五倍)巨大的优势,grep的,除非你更换\;+的查找/ EXEC组合。然后grep只能“快”大约30%。grep语法也是人类可读的:)。
Kjell Andreassen 2014年

同意,因为这很明显。某些busybox没有GREP命令。
hornetbzz

10
还请注意,您可以使用--exclude-dir={dir1,dir2}
suh

4
我毫不奇怪,这node_modules是典范的例子。
pdoherty926

982

最新版本的GNU Grep(> = 2.5.2)提供:

--exclude-dir=dir

dir从递归目录搜索中排除与模式匹配的目录。

因此,您可以执行以下操作:

grep -R --exclude-dir=node_modules 'some pattern' /path/to/search

有关语法和用法的更多信息,请参见

对于较旧的GNU Greps和POSIX Grep,请find按照其他答案中的建议使用。

或者只是使用ack编辑:或Silver Searcher)完成它!


4
@Manocho:如果您认为ack很棒,请尝试“ Silver Searcher”,并查看速度提高!
Johnsyweb

30
不耐烦的语法:--exclude-dir=dir使用grep的正则表达式模式,而不是 shell的文件范围。模式在相对于当前目录的路径上工作。因此,使用模式--exclude-dir=dir,没有--exclude-dir="/root/dir/*"
tanius

15
如果您想从搜索中排除多个目录,是否有比使用更好的选择:$ grep -r --exclude-dir=dir1 --exclude-dir=dir2 "string" /path/to/search/dir
Darshan Chaudhary

4
我可能比任何一个理智的人都花了太多时间,但是我一生无法弄清楚如何从搜索中排除子目录- grep -r --exclude-dir=public keyword .可以,但grep -r --exclude-dir='public/dist' keyword .不能。我尝试添加正则表达式通配符,转义字符等,但似乎无济于事。
dkobozev '16

72
排除多个目录,例如:grep -r "Request" . --exclude-dir={node_modules,git,build}
maverick97

77

如果要排除多个目录

“ r”表示递归,“ l”仅打印包含匹配项的文件名,“ i”忽略大小写:

grep -rli --exclude-dir={dir1,dir2,dir3} keyword /path/to/search

示例:我想查找包含单词“ hello”的文件。我想搜索 proc目录,引导目录,sys目录和目录之外的所有linux 目录:

grep -rli --exclude-dir={proc,boot,root,sys} hello /

注意:上面的示例必须是root

注释2(根据@skplunkerin):请勿在逗号后添加空格 {dir1,dir2,dir3}


5
注意:请勿在{dir1,dir2,dir3}
skplunkerin中

谢谢,在通过SVN工作区进行grep -Irsn --exclude-dir=.svn 'foo' .
复制

1
您可以--exclude-dir多次提供该选项。
沃尔夫

44

这个语法

--exclude-dir={dir1,dir2}

通过外壳(例如Bash)而不是通过grep扩展为:

--exclude-dir=dir1 --exclude-dir=dir2

引用将阻止外壳扩展它,因此这将不起作用:

--exclude-dir='{dir1,dir2}'    <-- this won't work

与一起使用的模式与--exclude-dir--exclude选项的手册页中描述的模式相同:

--exclude=GLOB
    Skip files whose base name matches GLOB (using wildcard matching).
    A file-name glob can use *, ?, and [...]  as wildcards, and \ to
    quote a wildcard or backslash character literally.

外壳一般 尝试自行扩展这种模式,因此,为避免这种情况,应引用它:

--exclude-dir='dir?'

您可以将花括号和带引号的排除模式一起使用,如下所示:

--exclude-dir={'dir?','dir??'}

模式可以跨越多个路径段:

--exclude-dir='some*/?lse'

这将排除目录topdir/something/else


13

经常使用:

grep可以与-r(递归),i(忽略大小写)和-o(仅打印部分匹配的行)结合使用。要排除files使用--exclude并排除目录使用--exclude-dir

放在一起,您最终会得到以下结果:

grep -rio --exclude={filenames comma separated} \
--exclude-dir={directory names comma separated} <search term> <location>

描述它使它听起来比实际复杂得多。用一个简单的例子更容易说明。

例:

假设我要在所有显式设置字符串值的地方搜索当前项目 debugger调试会话期间在,现在希望查看/删除。

我编写了一个脚本findDebugger.sh,用于grep查找所有事件。然而:

对于文件排除-我希望确保将.eslintrc其忽略(实际上具有删除规则,debugger因此应排除在外)。同样,我也不想在任何结果中引用我自己的脚本。

对于目录排除-我希望排除,node_modules因为它包含许多确实引用的库,debugger并且我对那些结果不感兴趣。我也只想省略.idea.git隐藏目录,因为我也不在乎那些搜索位置,而是希望保持搜索性能。

因此,结果如下-我创建了一个名为的脚本findDebugger.sh

#!/usr/bin/env bash
grep -rio --exclude={.eslintrc,findDebugger.sh} \
--exclude-dir={node_modules,.idea,.git} debugger .

我相信“ r”选项应使用大写“ -R”打印。
hornetbzz

1
有趣。“ r”一直在nix和mac上为我工作。
arcseldon '18

当我写下答案时,我用过-R(我不记得现在为什么了)。我通常使用-r。事实证明,大写版本遵循符号链接。瓷砖。
Johnsyweb

@Johnsyweb-谢谢。支持您的答案-不记得何时,可能是在2016年我添加了这个:)
arcseldon

10

您可以尝试类似 grep -R search . | grep -v '^node_modules/.*'


34
在某些情况下不是一个很好的解决方案。例如:如果“ node_modules”目录是一个很大的目录,并且有很多误报匹配(因此需要过滤掉目录),那么第一个grep会浪费大量时间搜索子目录,然后浪费第二个grep过滤时间淘汰赛。在第一个grep本身中排除node_modules更快。
GuruM

2
我不在乎速度缓慢,我可以看一下命令并知道它的作用
Funkodebat 2014年

1
同上对古鲁的评论。在我的情况下,/var一阵挂起挂起/var/run。因此,我首先要避免使用目录的原因。
jww 2015年

3
--exclude-dir是截至2016
Omar Tariq

10

如果您正在git存储库中查找代码,并且node_modules位于.gitignore,则可以使用git grepgit grep在工作树中搜索跟踪的文件,而忽略所有内容.gitignore

git grep "STUFF"

这是非常有用的技巧。谢谢。
NKM


2

一个简单的工作命令:

root/dspace# grep -r --exclude-dir={log,assetstore} "creativecommons.org"

上面我在当前目录“ dspace”中为文本“ creativecommons.org”添加了grep,并排除了目录{log,assetstore}。

做完了


整洁,在括号中包括几个目录
Mijo

2

这里给出了许多正确的答案,但是我要补充这一点,以强调一点,这导致一些匆忙的尝试之前失败了:exclude-dir采用模式,而不是目录的路径。

说您的搜索是:

grep -r myobject

而且您会注意到,您的输出中混杂了来自的结果src/other/objects-folder。此命令不会给您预期的结果:

grep -r myobject --exclude-dir=src/other/objects-folder

您可能想知道为什么exclude-dir不起作用!要实际上从中排除结果objects-folder,只需执行以下操作:

grep -r myobject --exclude-dir=objects-folder

换句话说,仅使用文件夹名称而不是路径。一旦知道就很明显。

从手册页:

--exclude-dir = GLOB
跳过任何名称后缀与模式GLOB相匹配的命令行目录。递归搜索时,请跳过其基本名称与GLOB匹配的所有子目录。忽略GLOB中的任何多余的斜杠。




-1

一种更简单的方法是使用“ grep -v”过滤结果。

grep -i needle -R * | grep -v node_modules


12
这实际上是3年前DipSwitch提供的答案。它也有同样的问题。
jww
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.