关于linux:如何从grep -R中排除目录?

How can I exclude directories from grep -R?

我想遍历所有子目录,除了"node_modules"目录。


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

1
--exclude-dir=dir

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

所以你可以这样做:

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

有关语法和用法的详细信息,请参阅

  • 文件和目录选择的GNU手册页
  • 相关的stackoverflow应答使用grep--exclude/--include语法通过某些文件不grep

对于较老的GNU greps和posix grep,使用其他答案中建议的find

或者只需使用ack(编辑:或银搜索)就可以了!


方案1(结合findgrep)

此解决方案的目的不是处理grep性能,而是显示一个可移植的解决方案:还应与早于2.5的busybox或gnu版本一起使用。

使用find排除目录foo和bar:

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

然后结合findgrep的非递归使用,作为一种可移植的解决方案:

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

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

你已经知道这个解决方案了,但是我添加它是因为它是最新和最有效的解决方案。注意,这是一个不太可移植的解决方案,但更具可读性。

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

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

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

方案3(Ag)

如果您经常搜索代码,AG(Silver Searcher)是grep的一个更快的替代品,它是为搜索代码而定制的。例如,它会自动忽略.gitignore中列出的文件和目录,因此您不必一直向grepfind传递同样繁琐的排除选项。


如果要排除多个目录:

"r"表示递归,"l"表示只打印包含匹配项的文件名,"i"表示忽略大小写区别:

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

示例:我想查找包含单词"hello"的文件。我要在所有Linux目录中搜索,proc目录、boot目录、sys目录和root目录除外:

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

注意:上面的示例需要是根

注2(根据@skpunkerin):不要在{dir1,dir2,dir3}中的逗号后添加空格。


这个语法

1
--exclude-dir={dir1,dir2}

由shell(例如bash)而不是grep扩展到:

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

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

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

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

1
2
3
4
--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.

shell通常会尝试扩展这样的模式本身,因此为了避免这种情况,您应该引用它:

1
--exclude-dir='dir?'

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

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

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

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

这将排除像topdir/something/else这样的目录。


经常使用:

grep可与-r(递归)、i(忽略大小写)和-o一起使用(只打印与部分行匹配的部分)。要排除files,请使用--exclude,要排除目录,请使用--exclude-dir

把它放在一起,你会得到如下的结果:

1
2
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的脚本:

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


你可以试试像grep -R search . | grep -v '^node_modules/.*'这样的东西。


如果您在Git存储库中对代码进行了大量的映射,并且node_modules在您的.gitignore中,则可以使用git grepgit grep搜索工作树中的跟踪文件,忽略.gitignore中的所有内容。

1
git grep"STUFF"

非常有用,特别是对于那些处理node.js的人,我们希望避免在"node_modules"中搜索:

1
find ./ -not -path"*/node_modules/*" -name"*.js" | xargs grep keyword

这个对我有用

grep -R --exclude-dir=


一个简单的工作命令:

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

上面是当前目录"dspace"中文本"creativecommons.org"的grep,不包括dirs log,assetstore。

完成。


1
find . ! -name"node_modules" -type d


一个简单的方法是使用grep-v过滤结果。

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