Bash grep不包括文件名模式
我读过Bash grep不包括文件名模式,bash,shell,grep,Bash,Shell,Grep,我读过 但在我的世纪6.4,当我 grep --exclude=*.cmd ckim * -r 我在*.cmd文件中看到了许多灰色的行。 因此,排除选项似乎对我不起作用。 怎么了? 我当然可以做这样的事情 grep ckim \`find . -name \*.c -print\` 但是我想知道为什么grep不起作用。使用作为路径规范,而不是* grep -r --exclude \*.cmd ckim . 你也可以这样做 grep -rn ckim * | grep -v '\.cmd
但在我的世纪6.4,当我
grep --exclude=*.cmd ckim * -r
我在*.cmd文件中看到了许多灰色的行。因此,排除选项似乎对我不起作用。
怎么了?
我当然可以做这样的事情
grep ckim \`find . -name \*.c -print\`
但是我想知道为什么grep不起作用。使用
作为路径规范,而不是*
grep -r --exclude \*.cmd ckim .
你也可以这样做
grep -rn ckim * | grep -v '\.cmd'
您可以引用以下模式:
grep -r --exclude="*.cmd" "ckin" ./
PS./
是当前目录
我在*.cmd文件中看到了很多灰色的行。因此,排除选项似乎对我不起作用。
有一个名为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
)搜索字符串skim
,从f.cmd
、g.sh
和sub
开始,但不包括与模式“*.cmd”匹配的任何文件
结果是:
# nullglob is unset
sh$ grep --exclude=*.cmd ckim * -r
sub/i.sh:ckim
# nullglob is set
sh$ grep --exclude=*.cmd ckim * -r
sub/i.sh:ckim
sub/h.cmd:ckim
但是如果在您的环境中设置了选项nullglob
,则相同的命令将扩展为:
grep ckim f.cmd g.sh sub -r
请注意整个--exclude=…
是如何消失的。因此,结果是:
# nullglob is unset
sh$ grep --exclude=*.cmd ckim * -r
sub/i.sh:ckim
# 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
如果要从中排除某些要grep的文件,应使用
-l
选项
grep -l --exclude=*.cmd ckim * -r
您需要包含
pattern
参数。在我的测试中,即使使用了*
,该命令仍然有效。显式文件参数仍被筛选。@konsolebox:ACK with UbuntuI think
with-r
更清晰,不会导致外壳扩展出现不必要的行为。@konsolebox:ACK with RHEL7这有不必要的行为,假设文件中的行有something.cmd
即使文件名不包含\.cmd
是,它也不会显示该行。它有一些不需要的行为。。。但在同一行上使用“.cmd”时发生ckim的可能性会小得多。除非OP设置了nullglob
,否则不会产生显著差异--exclude=*.cmd
不太可能与单个文件匹配,并将保持原样作为参数。这是正确的做法,但并没有给出解决方案。@konsolebox,我必须承认我对nullglob
知之甚少,但shopt
说它关闭了,仍然有效。我遗漏了什么吗?它应该有用,但即使没有被引用,它仍然会有用。事实上,我的假设可能是错误的,您的代码可能确实能够帮助解决这个问题——不是因为您帮助它防止自身扩展到文件,而是因为您帮助它防止在启用nullglob
时将其置为空。由于引用,防止了任何类型的路径名扩展。我不敢相信我真的忽略了那部分。