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

Che*_*ony 14 shell grep

我正在尝试递归搜索字符串,grep但我得到了这个:

$ grep -r "stuff" *
grep: unrecognized option '---corporate-discount.csv'
Usage: grep [OPTION]... PATTERN [FILE]...
Try 'grep --help' for more information.
Run Code Online (Sandbox Code Playgroud)

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

ica*_*rus 43

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

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

grep -r -e "stuff" -- *
Run Code Online (Sandbox Code Playgroud)

会做你想做的。在-e万一有stuff一个开始-为好。

或者,您也可以使用:

grep -r -e "stuff"  ./*
Run Code Online (Sandbox Code Playgroud)

如果-当前目录中有一个文件被调用,后者也可以避免这个问题。即使在--分隔符之后,也grep解释-为标准输入,./-而是-当前目录中调用的文件。


ImH*_*ere 8

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

echo [!-]*
Run Code Online (Sandbox Code Playgroud)

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

echo !(-*)
Run Code Online (Sandbox Code Playgroud)

例如:在包含此文件的目录中

$ echo *
a b c ---corporate-discount.csv d -e --option.txt
Run Code Online (Sandbox Code Playgroud)

将仅列出(如果extglob处于活动状态):

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

$ echo [!-]*
a b c d
Run Code Online (Sandbox Code Playgroud)

但是,如果您想要处理所有文件,同时告诉 grep 避免解释用 a-作为选项声明的文件,那么只需添加一个./

grep -r "stuff" ./*
Run Code Online (Sandbox Code Playgroud)

或者,如果可以保证-列出的文件中不存在被调用的文件(grep 将把一个alone 解释-从 stdin 读取),您可以使用:

grep -r -- "stuff" *
Run Code Online (Sandbox Code Playgroud)

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