grep 对带有破折号的文件名感到困惑

grep 对带有破折号的文件名感到困惑

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

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

grep: unrecognized option '------.js'
Usage: grep [OPTION]... PATTERN [FILE]...
Try 'grep --help' for more information.

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

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

我正在运行 Arch Linux。

答案1

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

grep pattern --whatever

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

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

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

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

无论如何,如果你这样做,POSIXLY_CORRECT 也救不了你

grep -e pattern *.js

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

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

grep -e pattern -- *.js
grep -- pattern *.js

或使用:

grep -e pattern ./*.js

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

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

答案2

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

grep -- <string> <filename>

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

答案3

只是为了与其他人一起发表 TLDR 答案明显的使固定,

grep -e pattern ./*.js

这适用于不具有该--选项的命令;尽管它得到了相当广泛的支持,但并非所有命令都可以处理它。

(另请注意,它-e同样可以消除歧义图案以破折号开头。您当然也可以使用类似的方法来解决这个问题,[-]pattern但这不适用于grep -F;如果模式是用户提供的,最好不要弄乱它。)

在“(几乎)总是引用你的变量”之后,这可能是 shell 编程中第二个最常见的问题 - 通配符匹配和用户提供的数据可能并且偶尔会包含前导破折号,所以你最好做好准备。

答案4

find . -name '-*' -exec rename 's/[- ]//' {} \;

相关内容