我在目录树中寻找字符串foo=在文本文件中。在一个普通的Linux机器上,我有bash shell:

grep -ircl "foo=" *

目录中还有许多匹配“foo=”的二进制文件。由于这些结果不相关并降低了搜索速度,所以我希望grep跳过搜索这些文件(主要是JPEG和PNG图像)。我该怎么做呢?

我知道有——exclude=PATTERN和——include=PATTERN选项,但模式格式是什么?grep的手册页说:

--include=PATTERN     Recurse in directories only searching file matching PATTERN.
--exclude=PATTERN     Recurse in directories skip file matching PATTERN.

搜索grep包括,grep包括排除,grep排除和变体没有找到任何相关的

如果有更好的方法只在某些文件中进行grepping,我完全赞成;移动有问题的文件是行不通的。我不能只搜索某些目录(目录结构很混乱,到处都是东西)。此外,我不能安装任何东西,所以我必须使用常用工具(如grep或建议的find)。


当前回答

如果您只想跳过二进制文件,我建议您查看-I(大写I)选项。它忽略二进制文件。我经常使用以下命令:

grep -rI --exclude-dir="\.svn" "pattern" *

它会递归搜索,忽略二进制文件,并且不会在Subversion隐藏文件夹中查找我想要的任何模式。我在我工作的盒子上用"grepsvn"作为别名。

其他回答

如果您只想跳过二进制文件,我建议您查看-I(大写I)选项。它忽略二进制文件。我经常使用以下命令:

grep -rI --exclude-dir="\.svn" "pattern" *

它会递归搜索,忽略二进制文件,并且不会在Subversion隐藏文件夹中查找我想要的任何模式。我在我工作的盒子上用"grepsvn"作为别名。

我在很长一段时间后发现,你可以添加多个包含和排除,比如:

grep "z-index" . --include=*.js --exclude=*js/lib/* --exclude=*.min.js

使用shell globbing语法:

grep pattern -r --include=\*.cpp --include=\*.h rootdir

——exclude的语法是相同的。

注意,星号用反斜杠进行转义,以防止它被shell展开(引用它,例如——include="*.cpp",也同样有效)。否则,如果当前工作目录中有任何与该模式匹配的文件,命令行将展开为类似grep模式的内容-r——include=foo.cpp——include=bar.cpp rootdir,这将只搜索名为foo.cpp和bar.cpp的文件,这很可能不是您想要的。

更新2021-03-04

我编辑了原始答案,删除了大括号展开的使用,大括号展开是Bash和zsh等几个shell提供的功能,用于简化这样的模式;但请注意,大括号展开并不符合POSIX shell。

最初的例子是:

grep pattern -r --include=\*.{cpp,h} rootdir

查找根目录rootdir下的所有.cpp和.h文件。

Grep 2.5.3引入了——exclude-dir参数,它将以您想要的方式工作。

grep -rI --exclude-dir=\.svn PATTERN .

你也可以设置一个环境变量:GREP_OPTIONS="——exclude-dir=\.svn"

不过我支持安迪投ack,这是最好的。

我发现grepping grep的输出有时非常有用:

grep -rn "foo=" . | grep -v "Binary file"

不过,这实际上并没有阻止它搜索二进制文件。