grep 排除文件名模式

Posted

技术标签:

【中文标题】grep 排除文件名模式【英文标题】:grep excluding file name pattern 【发布时间】:2014-09-10 08:05:46 【问题描述】:

我读过 Use grep --exclude/--include syntax to not grep through certain files 但在我的 CentOS6.4 中,当我这样做时

grep --exclude=*.cmd ckim * -r

我从 *.cmd 文件中看到很多 grepped 行。 所以似乎排除选项对我不起作用。 怎么了? 当然我可以做类似的事情

grep ckim \`find . -name \*.c -print\`

但我想知道为什么 grep 不起作用。

【问题讨论】:

你需要包含pattern参数。 【参考方案1】:

你可以引用模式:

grep -r --exclude="*.cmd"  "ckim" ./

PS。 ./是当前目录

【讨论】:

除非 OP 设置了nullglob,否则这不会产生显着差异。 --exclude=*.cmd 不太可能匹配单个文件,并且将保持原样作为参数。这是正确的做法,但没有给出解决方案。 @konsolebox,我必须承认我对nullglob 了解不多,但shopt 说它是off 并且仍然有效。我错过了什么吗? 它应该可以工作,但即使没有引用它仍然可以。实际上我的假设可能是错误的,并且您的代码实际上可能能够帮助解决问题 - 不是因为您帮助它防止自身扩展到文件,而是因为您帮助防止它在 @987654328 时失效@ 已启用。由于引用,可以防止任何类型的路径名扩展。我不敢相信我真的忽略了那部分。【参考方案2】:

使用. 代替* 作为路径规范。

grep -r --exclude \*.cmd ckim .

【讨论】:

在我的测试中,即使使用了*,该命令仍然有效。显式文件参数仍会被过滤。 @konsolebox: 用 Ubuntu 确认 我认为.-r 更清晰,不会导致不必要的外壳扩展行为。 @konsolebox: 使用 RHEL7 确认【参考方案3】:

你也可以这样做

grep -rn ckim * | grep -v '\.cmd'

【讨论】:

这有不想要的行为,想象一下文件内的行有something.cmd,即使文件名不包含\.cmd,它也不会显示该行 是的,它有一些不受欢迎的行为......但是在同一行使用 '.cmd' 发生 ckim 的可能性要小得多【参考方案4】:

我从 *.cmd 文件中看到很多 grepped 行。所以看来排除选项对我不起作用。

有一个名为nullglob 的shell 选项可以在没有匹配文件时控制shell 模式的扩展。


所以,给定以下环境:

sh$ touch f.cmd g.sh
sh$ mkdir sub
sh$ echo ckim > sub/h.cmd
sh$ echo ckim > sub/i.cmd

my 系统上(nullglob 未设置),以下命令:

grep --exclude=*.cmd ckim * -r

被外壳扩展(“理解”)为:

grep --exclude=*.cmd ckim f.cmd g.sh sub -r

也就是说,我将递归地 (-r) 搜索以f.cmdg.shg.shsub 开头的字符串skim,但不包括与模式'* 匹配的任何文件.cmd'。

结果是:

# nullglob is unset
sh$ grep --exclude=*.cmd ckim * -r
sub/i.sh:ckim

但是如果在您的环境中设置了选项nullglob,则相同的命令扩展为:

grep ckim f.cmd g.sh sub -r

注意整个 --exclude=... 是如何消失的。所以结果是:

# nullglob is set
sh$ grep --exclude=*.cmd ckim * -r
sub/i.sh:ckim
sub/h.cmd:ckim

现在,解释一下。当 shell 遇到 glob 模式(即:包含 *? 或更多特殊字符)时,它会使用匹配的文件对其进行扩展。 但是如果没有匹配的文件,它要么让模式保持原样(如果nullglob 没有设置)或者用“nothing”替换它(如果nullglob已设置)。

这里的模式是--include=*.cmd(在整个,因为那里没有空间)。万一您有一个与此模式匹配的文件,它将被替换。否则,要么“原样”要么完全删除——取决于nullglob


您可以轻松地显示、设置 (-s) 或取消设置 (-u) 当前 bash 的 nullglob 选项的状态:

sh$ shopt nullglob
nullglob        on

sh$ shopt -u nullglob
sh$ shopt nullglob
nullglob        off

sh$ shopt -s nullglob
sh$ shopt nullglob
nullglob        on

【讨论】:

【参考方案5】:

如果您想从 grep 中排除某些文件,您应该使用 -l 选项。

grep -l --exclude=*.cmd ckim * -r

【讨论】:

以上是关于grep 排除文件名模式的主要内容,如果未能解决你的问题,请参考以下文章

如何从 ack (ack-grep) 中排除特定文件?

如何从 git grep 搜索中排除某些目录/文件

使用查找时排除文件夹[重复]

rm排除指定文件或指定文件夹下文件

Linux三剑客入门

从 grep 中排除 .svn 目录 [重复]