我想遍历所有子目录,除了"node_modules"目录。
- 结合查找和grep
- 见superuser.com/q/66715/59933
- 只需键入"man grep",您就会看到--排除,和--排除这里列出的dir选项--在这个问题的标题中,我假设您已经知道grep…
- 如果您在Git存储库中大量使用代码,而node_modules在您的.gitignore中,那么git grep"STUFF"是最简单的方法。git grep搜索工作树中的跟踪文件,忽略.gitignore中的所有内容。
- 例如node:grep -R --exclude-dir={node_modules,bower_components}"MyString" | cut -c1-"$COLUMNS"--此外,您可以在shell中将其别名为"nodegrep"或其他名称,并使用命令参数作为字符串输入。
GNU GREP的最新版本(>=2.5.2)提供:
它从递归目录搜索中排除了与模式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(编辑:或银搜索)就可以了!
- 我刚试过确认。工作很好。
- @马诺乔:如果你认为ack很好,试试银搜索器,看看速度有没有提高!
- 不耐烦的语法:--exclude-dir=dir使用grep的正则表达式模式,而不是shell的文件globbing。模式在相对于当前目录的路径上工作。所以使用模式--exclude-dir=dir,而不是--exclude-dir="/root/dir/*"。
- 注意:如果您的grep不支持,您可以使用ggrep。
- 如果您希望从搜索中排除多个目录,有没有比使用更好的选择:$ grep -r --exclude-dir=dir1 --exclude-dir=dir2"string" /path/to/search/dir?
- @达尚乔杜里:你说的"更好"是什么意思?这对我来说是个好办法。
- @约翰西韦布,我希望有什么事情我不必多次提到江户记1(2)。
- 不幸的是,OS X 10.11附带的默认grep仍然是2.5.1
- @泰勒龙:我用的是自制双面打印的grep:github.com/homebrew/homebrew-dupes/blob/master/grep.rb
- 我可能比任何理智的人花了太多的时间在这个问题上,但我一辈子都想不出如何将子目录排除在搜索范围之外-grep -r --exclude-dir=public keyword .工作,但grep -r --exclude-dir='public/dist' keyword .不工作。我尝试添加regex通配符、转义字符等,但似乎没有什么帮助。
- 排除多个目录,如so:grep -r"Request" . --exclude-dir={node_modules,git,build}。
- 有没有一种方法可以将它添加到我所做的所有grep命令中,这样我就不需要每次都手动键入它了?
- @马修赫布斯特:你可以用别名或脚本来包装grep。
- @Matthewherst您可以根据建议创建别名,或者使用grep_选项(或类似的)变量导出别名。我更喜欢别名路由,以防我确实需要在排除的目录中搜索,或者使用不同的选项,我可以绕过别名。
- @dragon788:GREP_OPTIONS已弃用:git.savannah.gnu.org/cgit/grep.git/commit/…
- @dkobozev要排除特定的子目录,您必须从点开始,因此使用grep -r --exclude-dir='./public/dist' keyword应该是您要查找的内容。
方案1(结合find和grep)
此解决方案的目的不是处理grep性能,而是显示一个可移植的解决方案:还应与早于2.5的busybox或gnu版本一起使用。
使用find排除目录foo和bar:
1
| find /dir \( -name foo -prune \) -o \( -name bar -prune \) -o -name"*.sh" -print |
然后结合find和grep的非递归使用,作为一种可移植的解决方案:
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中列出的文件和目录,因此您不必一直向grep或find传递同样繁琐的排除选项。
- 这种组合搜索速度比--exclude-dir=dir快,显示的结果用颜色显示,易于阅读。
- "这个组合"对我来说,find ... -exec并不比grep --exclude-dir快。grep的巨大优势(大约是26K+文件速度的五倍,在HDD上过滤掉38K+文件),除非您用+替换\;以用于find/exec组合。那么grep"只"快30%。grep语法也是人类可读的:)。
- 同意,因为这很明显。某些Busybox没有grep命令。
- 以东十一〔八〕对我来说很好。ag text .(银搜索者)的作品非常出色
- 还要注意,可以用--exclude-dir={dir1,dir2}排除多个
- 我一点也不惊讶于node_modules是典型的例子。
如果要排除多个目录:
"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}中的逗号后添加空格。
- 注意:不要在{dir1,dir2,dir3}中的逗号后加空格。
- 谢谢,通过SVN工作区时很方便:grep -Irsn --exclude-dir=.svn 'foo' .。
- 您可以多次提供--exclude-dir选项。
这个语法
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?','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 . |
- 我认为"R"选项应该用大写字母"-R"打印。
- 很有趣。""R"一直在尼克斯和麦克为我工作。
你可以试试像grep -R search . | grep -v '^node_modules/.*'这样的东西。
- 在某些情况下不是很好的解决方案。例如:如果"node_modules"目录是一个有大量假阳性匹配的大目录(因此需要筛选出目录),那么第一个grep会浪费大量时间在子目录中搜索,然后第二个grep会筛选出匹配项。在第一个grep中排除节点模块更快。
- 我不在乎速度慢,我可以看一下命令,知道它做了什么。
- 古鲁的评论也是如此。在我的例子中,当它击中/var/run时,一个grep的/var挂起。因此,我首先要避免使用目录。
- 截至2016年,--exclude-dir是最佳解决方案。
如果您在Git存储库中对代码进行了大量的映射,并且node_modules在您的.gitignore中,则可以使用git grep。git grep搜索工作树中的跟踪文件,忽略.gitignore中的所有内容。
非常有用,特别是对于那些处理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 |
- 您可以通过pipe和xargs将上述命令传递给"grep-r"…
一个简单的方法是使用grep-v过滤结果。
grep -i needle -R * | grep -v node_modules
- 这实际上是3年前Dipswitch提供的相同答案。它也有同样的问题。