使用grep--的排除/包括语法不grep通过某些文件

我正在目录树中的文本文件中寻找字符串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排除和变体没有找到任何相关的内容

如果有更好的方法只在某些文件中检查,我完全赞成;移动违规文件不是一个选择。我不能只搜索某些目录(目录结构一团糟,到处都是东西)。此外,我不能安装任何东西,所以我必须使用常用工具(如grep或建议的找到)。

794177 次浏览

使用shell全局语法

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

--exclude的语法是相同的。

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

更新时间2021-03-04

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

最初的例子是:

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

搜索根目录rootdir中的所有.cpp.h文件。

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

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

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

查找和xargs是你的朋友。使用它们来过滤文件列表,而不是grep的--排除

尝试类似

find . -not -name '*.png' -o -type f -print | xargs grep -icl "foo="

习惯这一点的好处是,它可以扩展到其他用例,例如计算所有非png文件中的行数:

find . -not -name '*.png' -o -type f -print | xargs wc -l

删除所有非png文件:

find . -not -name '*.png' -o -type f -print | xargs rm

正如注释中指出的,如果某些文件的名称中可能有空格,请改用-print0xargs -0

试试这个:

$ find . -name "*.txt" -type f -print | xargs file | grep "foo=" | cut -d: -f1

创建于:http://www.unix.com/shell-programming-scripting/42573-search-files-excluding-binary-files.html

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

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

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

请看看ack,它正是为这些情况而设计的。你的例子

grep -ircl --exclude=*.{png,jpg} "foo=" *

用ack作为

ack -icl "foo="

因为默认情况下ack从不查看二进制文件,默认情况下-r是打开的。如果你只想要CPP和H文件,那就这样做

ack -icl --cpp "foo="

这些脚本不能解决所有问题……试试这个更好:

du -ha | grep -i -o "\./.*" | grep -v "\.svn\|another_file\|another_folder" | xargs grep -i -n "$1"

这个脚本更好,因为它使用“真正的”正则表达式来避免搜索目录。只需在grep-v上用“\|”分隔文件夹或文件名

好好享受吧!在我的linux shell上找到的!XD

建议的命令:

grep -Ir --exclude="*\.svn*" "pattern" *

从概念上讲是错误的,因为--排除适用于基本名称。换句话说,它只会跳过当前目录中的. svn。

grep 2.5.3引入了--exclude-dir参数,它将按照您想要的方式工作。

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

您还可以设置环境变量:GREP_OPTIONS="--exclude-dir=\.svn"

我会第二次安迪的投票给ack,这是最好的。

GNUgrep--binary-files=without-match选项让它跳过二进制文件。(相当于别处提到的-I开关。)

(这可能需要grep; 2.5.3的最新版本,至少。

我是个业余爱好者,当然,但这是我的~/。bash_profile看起来:

export GREP_OPTIONS="-orl --exclude-dir=.svn --exclude-dir=.cache --color=auto" GREP_COLOR='1;32'

请注意,要排除两个目录,我必须使用--exout-dir两次。

在grep 2.5.1中,您必须将此行添加到~/. bashrc或~/. bash配置文件

export GREP_OPTIONS="--exclude=\*.svn\*"

忽略grep中的所有二进制结果

grep -Ri "pattern" * | awk '{if($1 != "Binary") print $0}'

awk部分将过滤掉所有二进制文件foo匹配行

看这个。

grep --exclude="*\.svn*" -rn "foo=" * | grep -v Binary | grep -v tags

试试这个:

  1. 在currdir…下创建一个名为“--F”的文件夹(或链接另一个重命名为“--F”即double-minus-F的文件夹)。
  2. #> grep -i --exclude-dir="\-\-F" "pattern" *

如果你不反对使用find,我喜欢它的-prune功能:查找[目录]\-name"pattern_to_exclude"-prune\-o-name"another_pattern_to_exclude"-prune\-o-name"pattern_to_INCLUDE"-print0\|xargs-0-I FILENAME grep-IR"模式"FILENAME

在第一行,您指定要搜索的目录。例如,.(当前目录)是有效路径。

在第2行和第3行,使用"*.png""*.gif""*.jpg"等等。尽可能多地使用这些-o -name "..." -prune结构,因为您有模式。

在第4行,你需要另一个-o(它指定了“或”到find),你想要的模式,并且你需要在它的末尾加上-print-print0。如果你只是想要修剪*.gif*.png等图像后剩下的“其他一切”,那么使用-o -print0,完成第4行。

最后,在第5行是xargs的管道,它接受每个结果文件并将它们存储在变量FILENAME中。然后它传递grep-IR标志,"pattern",然后FILENAMExargs扩展为find找到的文件名列表。

对于您的特定问题,语句可能看起来像:找到。\-name"*. png"-prune\-o-name"*. gif"-prune\-o-name"*. svn"-prune\-o-print0|xargs-0-I FILES grep-IR"foo="FILES

适用于tcsh. alias文件:

alias gisrc 'grep -I -r -i --exclude="*\.svn*" --include="*\."{mm,m,h,cc,c} \!* *'

我花了一段时间才弄清楚{mm, m, h, cc, c}部分不应该在引号内。基思

我在很长一段时间后发现了这一点,您可以添加多个包含和排除项,例如:

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

在CentOS 6.6/Grep 2.6.3上,我必须这样使用它:

grep "term" -Hnir --include \*.php --exclude-dir "*excluded_dir*"

注意缺少等号“=”(否则--include--excludeinclude-dir--exclude-dir将被忽略)

如果您以非递归方式搜索,您可以使用整体模式来匹配文件名。

grep "foo" *.{html,txt}

包括html和txt。它仅在当前目录中搜索。

要在子目录中搜索:

   grep "foo" */*.{html,txt}

在子目录中:

   grep "foo" */*/*.{html,txt}

在目录中也有许多二进制文件。我不能只搜索某些目录(目录结构一团糟)。有没有更好的方法只在某些文件中检查?

ripgrep

这是递归搜索当前目录的最快工具之一。它以Rust编写,构建在Rust的正则表达式引擎之上以获得最大效率。检查详细分析在这里

所以你可以运行:

rg "some_pattern"

它尊重您的.gitignore并自动跳过隐藏文件/目录和二进制文件。

您仍然可以使用-g/--glob自定义包含或排除文件和目录。全局规则匹配.gitignore个全局。检查man rg以获取帮助。

有关更多示例,请参阅:如何排除某些文件不匹配某些扩展名与grep?

在macOS上,您可以通过brew install ripgrep安装。

git grep

使用git grep,它针对性能进行了优化,旨在搜索某些文件。

默认情况下,它忽略二进制文件并且尊重您的.gitignore。如果您不使用Git结构,您仍然可以通过传递--no-index来使用它。

语法示例:

git grep --no-index "some_pattern"

有关更多示例,请参阅: