我遇到一个问题,当目录包含以破折号开头的文件时,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/[- ]//' {} \;