如何防止Bash扩展传递以“-”开头的文件作为参数?


14

我试图用递归搜索一个字符串,grep但是我得到了:

$ grep -r "stuff" *
grep: unrecognized option '---corporate-discount.csv'
Usage: grep [OPTION]... PATTERN [FILE]...
Try 'grep --help' for more information.

如何防止Bash传递以-as 开头的文件?



3
您真的不想阻止Shell传递这些文件,是吗?问题是,如何grep确定它们不是选项。
DonHolgo '19

11
...要清楚,bash不能控制将哪个结果视为选项还是作为参数;在接收程序的控制之下。例如,subprocess.Popen(['grep', '-r', '-e' 'stuff', '--corporate-discount.csv'])在Python中,您将得到相同的行为,而在任何地方都没有bash。
查尔斯·达菲,

1
相关阅读:Unix Wildcards Gone Wild,有关使用*in命令可能引起的安全性问题。通过使用可以避免所有这些情况./*
通配符

1
@Wildcard,--用作选项终止标记也是完全合理的;POSIX实用程序语法准则要求遵守它。参见准则10。(当然,并非所有程序都遵循POSIX准则,但是答案是要对违规程序的作者进行严格分类和/或将其逐出行业)。
查尔斯·达菲

Answers:


43

首先,请注意,以破折号开头的参数的解释取决于正在启动的程序, grep或其他程序。外壳没有直接的方法来控制它。

假设您要处理此类文件(而不是完全忽略它们),则grep与大多数程序一起,它被--视为指示选项的结束,因此

grep -r -e "stuff" -- *

会做你想要的。在-e有万一stuff有启动-,也有。

或者,您也可以使用:

grep -r -e "stuff"  ./*

如果-当前目录中有一个文件,后一种方法也可以避免该问题。即使在--分隔符之后,它也grep解释-为标准输入,而在当前目录中则./-是该文件-


8

为了防止Bash扩展传递以“-”开头的文件,可以使用:

echo [!-]*

可以在大多数shell中移植,或者特定于ksh,bash,zsh:

echo !(-*)

例如:在具有此文件的目录中

$ echo *
a b c ---corporate-discount.csv d -e --option.txt

仅列出(提供extglob处于活动状态):

$ shopt -s extglob
$ echo !(-*)
a b c d

$ echo [!-]*
a b c d

但是,如果要在告诉grep避免解释使用-as选项声明的文件的同时处理所有文件,则只需添加一个./

grep -r "stuff" ./*

或者,如果可以保证-列出的文件中不存在所谓的文件(grep将解释-从stdin读取的文件),则可以使用:

grep -r -- "stuff" *

是的,因为问题是关于bash(一个GNU shell)的问题,因此可以合理地假设GNU grep可用,可以安装或正在实际使用中。@StéphaneChazelas–
以撒

是的,a grep -r -- stuff *更简单,并且也适用于非GNUish抓取。所以:补充,谢谢。@StéphaneChazelas–
以撒

@Isaac我不会说这是一个合理的假设,“如果bash可用,那么GNU grep也将可用”。以FreeBSD为例:默认情况下未安装bash,以后可以安装bash,但是对grep没有影响-除非明确安装了GNU grep,否则它仍然是grep的BSD版本。但这只是个小问题。我喜欢通过extglob选择的替代方法,因此对答案+1了
Sergiy Kolodyazhnyy

2
grepFreeBSD上的AFAIK的@SergiyKolodyazhnyy 仍然是基于GNU的,grep并且仍然存在功能错误,即在非选项之后可以识别选项。甚至像OpenBSD这样的BSD都重写了它们,grep使它们与GNU兼容,以实现向后的可移植性(并在此处仍然显示这种行为)。在macOS上,sh是bash,但我希望他们的grep不会显示该行为,因为即使没有$ POSIXLY_CORRECT,macOS也应符合POSIX。在任何情况下,OP的grep 都是 GNU兼容的,因为它会给出该错误。
斯特凡Chazelas

1
又见echo [!-]*为KSH的(或标准等同bash -O extglob的)echo !(-*)
斯蒂芬·夏泽拉斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.