在OSX Zsh中,grep --include命令不起作用。

14

我正在遵循在如何在Linux上查找包含特定文本的所有文件?上的最佳答案来在我的项目中搜索字符串。

这是我的命令grep --include=*.rb -rnw . -e "pattern"

Zsh告诉我zsh:没有找到匹配项:--include=*.rb

看起来grep不支持--include选项。

当我输入grep --help时,它返回

usage: grep [-abcDEFGHhIiJLlmnOoPqRSsUVvwxZ] [-A num] [-B num] [-C[num]]
    [-e pattern] [-f file] [--binary-files=value] [--color=when]
    [--context[=num]] [--directories=action] [--label] [--line-buffered]
    [--null] [pattern] [file ...]

这里不需要使用--include

是我的grep版本太旧了吗?还是我的命令出了问题?

2个回答

26

FreeBSD/macOS的grep确实支持--include选项(请参见man grep;不幸的是,grep -h命令行帮助没有列出此选项),但问题在于选项参数*.rb未被引用起来

结果是,zsh 尝试在前面对--include=*.rb进行路径名扩展,但失败了,因为当前目录中没有与全局模式*.rb匹配的文件名称。
grep甚至无法执行。

由于您的意图是将*.rb不变的方式传递给grep,因此必须引用

grep --include='*.rb' -rnw . -e "pattern"     

要包含多个通配符:

  • 为每个添加--include选项;例如:

grep --include='*.rb' --include=='*.h*' -rnw . -e "pattern"     
  • 或者,在支持花括号扩展的shell中 - 特别是bashkshzsh - 您可以让您的shell为您创建这些多个选项,如下所示 - 请注意选择性引用(有关详细说明,请参见此答案):

    grep '--include=*.'{rb,'h*'} -rnw . -e "pattern"     
    

  • 仍然无法修复该模式 grep 'pattern' -rIn '--include=*.{c*,h*}' - linzuojian
    1
    @linzuojian,您正在尝试使用花括号扩展,但是(a)只有一些 shell 支持此功能,并且(b)仅在未引用时支持。grep本身不理解这个符号表示法。请查看我的更新,其中显示了如何正确使用花括号扩展,并提供了一个包含背景信息的答案链接。 - mklement0

    3
    如果您的 grep 不支持 --include,并且您不想仅为此安装 GNU grep,则有许多便携式方法可以执行相同的操作。简单来说,试试以下方法:
    find . -type f -name '*.rb' -exec grep -nw "pattern" /dev/null {} \;
    
    find 命令遍历目录(类似于 grep -r),查找文件名为 *.rb(类似于 --include 选项),/dev/null 的作用是当你在多个文件上运行 grep 时,它可以显示出稍微不同的输出格式。
    由于对每个文件都要单独运行一个 grep,所以这样做略微低效。如果速度太慢,请考虑使用 xargs(或者如果你的 find 支持,则使用 find -exec ... {} \+ 而不是 ... {} \;)。这是一个非常常见的任务,你应该可以轻易地找到成千上万个示例。
    你可能还想考虑一下ack,这是一个流行的、有点更加用户友好的替代品。它是自包含的,因此 "安装" 只需将其复制到您的 $HOME/bin 中。

    不是只有Linux,FreeBSD也支持--include;它只是没有在命令行帮助中列出(但在man grep中有);OP的问题是使用未加引号的通配符*.rb。为了避免多个grep调用的低效率,只需使用+而不是\;,这会给您提供类似于xargs的行为:find . -type f -name '*.rb' -exec grep -nw "pattern" {} +。感谢ack提示-之前没有听说过。 - mklement0
    感谢您的更新。我不确定osx支持什么以及zsh带来了什么影响。我在答案中添加了find ... -exec ... \+;感谢您指出这一点。 - tripleee
    很高兴能帮忙;你提到了+特性,但实际上它是 POSIX 的一部分——请参见 http://man.cx/find。 你介绍中的语句会让人误认为只有GNU grep支持--include,不知道你是否能修改一下? - mklement0
    无论是否标准,我有一些盒子,其中GNU find版本太旧,不支持-exec ... \+(GNU find 4.1.20,Debian 3.1 [sic])。 - tripleee
    有趣,谢谢你告诉我。 (一个小提示:在\;中的\仅需要保护;不被_shell_(作为命令分隔符)解释 - \被shell“吃掉”,而find只看到;。由于+对shell来说不是特殊的,因此不需要以这种方式转义它(尽管也没有任何伤害),因此-exec ... {} +将起作用。但是,我可以看到有人可能会选择仍然使用它以获得对称性并且不必记住特殊情况。) - mklement0

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接