grep被带破折号的文件名弄糊涂了

agg*_*877 6 grep options filenames arguments

我遇到了一个问题,当目录包含以破折号开头的文件时,grep 会感到困惑。

例如,我有一个名为“ ------.js”的文件。当我做类似的事情时,grep somestring *我收到错误:

grep: unrecognized option '------.js'
Usage: grep [OPTION]... PATTERN [FILE]...
Try 'grep --help' for more information.
Run Code Online (Sandbox Code Playgroud)

这似乎是整个互联网都会问的那种问题,但我找不到任何东西。

我可以用类似的方法手动解决问题,
find . | while read f; do grep MYSTRING "$f"; done
但我想知道是否有更简单/更强大的解决方案。

我正在运行 Arch Linux。

Sté*_*las 9

作为罗密欧答案的补充,请注意

grep pattern --whatever
Run Code Online (Sandbox Code Playgroud)

POSIX 需要在文件中查找模式--whatever。那是因为在非选项参数之后不应识别任何选项(此处pattern)。

grep在这种情况下,GNU不符合 POSIX。可以通过将 POSIXLY_CORRECT 环境变量(具有任何值)传递到其环境中来使其兼容。

大多数 GNU 实用程序和实用程序使用 GNU 或getopt()/ 的兼容实现getopt_long()来解析命令行参数就是这种情况。

有明显的例外,例如env,从哪里env VAR=x grep --version获取 的版本grep,而不是env。另一个值得注意的例外是 GNU shell ( bash),其中解释器及其任何内置函数都不接受非选项参数之后的选项。甚至它getopts也无法以 GNU 方式解析选项。

无论如何,如果你这样做,POSIXLY_CORRECT 不会拯救你

grep -e pattern *.js
Run Code Online (Sandbox Code Playgroud)

(在那里,pattern不是非选项参数,它作为参数传递给-e选项,因此在此之后允许更多选项)。

因此,当您不能保证后面的内容不会以 a -(或+某些工具)开头时,将选项的结尾标记为 - 总是一个好主意:

grep -e pattern -- *.js
grep -- pattern *.js
Run Code Online (Sandbox Code Playgroud)

或使用:

grep -e pattern ./*.js
Run Code Online (Sandbox Code Playgroud)

(请注意,grep -- pattern *如果有一个名为 的文件-,则不会对您有帮助,whilegrep pattern ./*会起作用。grep -e "$pattern"应该使用,而不是grep "$pattern"以防$pattern它本身可能以 开头-)。

上世纪 90 年代中期曾有人尝试bash能够分辨getopt()哪些参数(通常是由 glob 扩展产生的参数)不应被视为选项(通过_<pid>_GNU_nonoption_argv_flags_环境变量),但由于它导致更多问题比它解决的要多。


Rom*_*nov 6

您可以尝试告诉“参数结束”的 grep 选项

grep -- <string> <filename>
Run Code Online (Sandbox Code Playgroud)

这将通知 grep 忽略下一个破折号作为参数并将它们作为命令行中的下一个元素