关于Unix:使用grep–exclude/–include语法在某些文件中不grep起作用

Use grep --exclude/--include syntax to not grep through certain files

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

1
grep -ircl"foo=" *

目录中还有许多与"foo!"匹配的二进制文件。由于这些结果不相关,搜索速度变慢,我希望grep跳过搜索这些文件(大多数是jpeg和png图像)。我该怎么做?

我知道有--exclude=PATTERN--include=PATTERN选项,但是模式格式是什么?grep的主页上写着:

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

在grep include、grep include exclude、grep exclude和variants上搜索未找到任何相关内容

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


使用shell globbing语法:

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

--exclude的语法相同。

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


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

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

它以递归方式搜索,忽略二进制文件,不在Subversion隐藏文件夹中查找我想要的任何模式。我在工作的时候把它化名为"grepsvn"。


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

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

使用ACK AS完成

1
ack -icl"foo="

因为Ack在默认情况下从不查找二进制文件,并且-r在默认情况下处于打开状态。如果你只想要cpp和h文件,那就做吧

1
ack -icl --cpp"foo="


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

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

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

不过,我会支持安迪对ACK的投票,这是最好的。


我发现这一点很长时间后,您可以添加多个include和excludes,例如:

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


建议的命令:

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

在概念上是错误的,因为--exclude在basename上工作。换句话说,它将只跳过当前目录中的.svn。


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

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

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

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

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


在Centos 6.6/grep 2.6.3上,我必须这样使用它:

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

注意,缺少等号"="(否则忽略--include--excludeinclude-dir--exclude-dir)


如果您不反对使用find,我喜欢它的-prune特性:ZZU1〔0〕

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

在2、3号线使用"*.png""*.gif""*.jpg"等。使用尽可能多的这些-o -name"..." -prune构造,就像使用模式一样。

在第4行,您需要另一个-o(它指定"或"到find),您想要的模式,并且您需要在它的末尾有-print-print0。如果您只想在修剪*.gif*.png等图像后保留"其他所有内容",则使用-o -print0第4行就结束了。

最后,在第5行是到xargs的管道,它获取每个生成的文件,并将它们存储在一个变量FILENAME中。然后通过grep-IR标志,"pattern"标志,然后由xargs扩展FILENAME成为find发现的文件名列表。

对于您的特定问题,声明可能如下所示:ZZU1〔1〕


当然,我是个业余爱好者,但我的~/.bash_简介如下:

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

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


git grep

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

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

示例语法:

1
git grep --no-index"some_pattern"

有关更多示例,请参见:

  • 如何从git grep搜索中排除某些目录/文件。
  • 检查文件中是否存在所有多个字符串或正则表达式

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

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

包括HTML和TXT。它只在当前目录中搜索。

要在子目录中搜索:

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

在子目录中:

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

试试这个:

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

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


看这个。

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


这些脚本并不能解决所有问题…请尝试更好的方法:

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

这个脚本非常好,因为它使用"real"正则表达式来避免搜索目录。只需在grep-v上用""分隔文件夹或文件名

好好享受吧!在我的Linux外壳上找到!除息的


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

尝试一下

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


In the directories are also many binary files. I can't search only certain directories (the directory structure is a big mess). Is there's a better way of grepping only in certain files?

ripgrep

这是设计用于递归搜索当前目录的最快工具之一。它是用Rust写的,建立在Rust的Regex引擎之上,以获得最大的效率。在这里检查详细的分析。

所以你可以跑:

1
rg"some_pattern"

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

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

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

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


适用于tcsh.alias文件:

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

我花了一段时间才发现m m、m、h、c c、c部分不应该在引号内。基思


gnu grep--binary-files=without-match选项使它跳过二进制文件。(相当于其他地方提到的-I开关。)

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


忽略grep的所有二进制结果

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

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


试试这个:

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