如何将grep --include选项用于多种文件类型?


98

当我想grep某个目录中的所有html文件时,请执行以下操作

grep --include="*.html" pattern -R /some/path

效果很好。问题是如何grep某个目录中的所有html,htm,php文件?

从这个使用grep --exclude /-include语法不通过某些文件进行grep看来,我可以执行以下操作

grep --include="*.{html,php,htm}" pattern -R /some/path

但可悲的是,它对我不起作用。
仅供参考,我的grep版本是2.5.1。

Answers:


137

您可以使用多个--include标志。这对我有用:

grep -r --include=*.html --include=*.php --include=*.htm "pattern" /some/path/

但是,您可以按照Deruijter建议进行操作。这对我有用:

grep -r --include=*.{html,php,htm} "pattern" /some/path/

不要忘记,您可以使用find并且可以将xargs这种事情用于:

find /some/path/ -name "*.htm*" -or -name "*.php" | xargs grep "pattern"

高温超导


1
我看到了问题。我使用--include =“ 。{html,php}”来防止shell扩展' ',同时阻止shell扩展{html,php}。--include = *中的等号似乎可以防止shell扩展'*'。
天涯漂子

xargs并不是真正的替代品;很多时候,当您需要此功能时,您处理的文件超出了xargs的处理能力。
詹姆斯·摩尔

2
@JamesMoore:看看GNU Parallel。它通常可以代替xargs也值得快速阅读。HTH。
史蒂夫

3
@tianyapiaozi:正确的是,括号扩展周围的引号是问题所在;但是,没有引号的情况下,作为嵌入它的令牌的一部分,它*仍然会受到影响,在这种情况下,它恰好不匹配任何内容,因为只有字面名称类似的文件才会匹配。为了安全起见,请引号(您可以单独使用)。作为额外的好处,在这种情况下,这使从视觉上更清楚地知道不是应由外壳执行的外壳。--include=foo.html*\*
mklement0

2
至于find解决方案:使用-exec grep "pattern" {} +而不是| xargs grep "pattern"更健壮(例如,使用空格处理文件名)以及更高效。
mklement0

32

使用{html,php,htm}只能作为工作括号扩展,这是一个非标准的(不是POSIX兼容)功能bashkshzsh

  • 换句话说:请勿尝试在目标脚本中使用它/bin/sh- 在这种情况下,请使用明确的多个--include参数。

  • grep本身并没有明白{...}的符号。

要识别括号扩展,它必须是命令行上未加引号的(一部分)令牌

大括号扩展会扩展为多个参数,因此在手头的情况下grep最终会看到多个 --include=...选项,就像您单独传递它们一样。

大括号扩展的结果易受globbing(文件名扩展)的影响,该陷阱有以下缺陷

  • 如果每个结果参数碰巧包含未引用的通配符,例如,则可以进一步扩展为匹配的文件名*
    尽管对于诸如这样的令牌来说,这是不太可能的--include=*.html(例如,您必须拥有一个从字面上命名为类似名称的文件--include=foo.html才能进行匹配),但总体上还是值得牢记。

  • 如果nullglobshell选项恰好是开启(shopt -s nullglob)和通配符匹配什么,参数会被丢弃

因此,对于完全健壮的解决方案,请使用以下命令:

grep -R '--include=*.'{html,php,htm} pattern /some/path
  • '--include=*.'由于被单引号引起来,因此被视为文字。这样可以防止无意中将其解释为通配符。*

  • {html,php,htm},-必要- 未引号的括号扩展[1] ,扩展为3个参数,由于{...} 直接跟随该'...'令牌,因此包含该令牌。

  • 因此,在shell删除引号之后,以下三个 文字参数最终传递给grep

    • --include=*.html
    • --include=*.php
    • --include=*.htm

[1]更准确地说,只有大括号扩展中与语法相关的部分必须不加引号,列表元素仍可以单独加引号,并且如果它们包含通配元字符,则它们可能在大括号扩展后导致不必要的通配;虽然在这种情况下不是必需的,但以上内容可以写为
'--include=*.'{'html','php','htm'}


1
非常感谢您的这篇文章。精彩的帖子不仅可以回答问题,而且可以教给您一些新的知识!对于我们这些需要编写与POSIX兼容的东西的人来说,这特别有用。使用Mac OS X的任何人都应该在这里查看!
sabalaba

@sabalaba:我很高兴听到它,但要明确一点:尽管括号扩展不符合POSIX,但它可以bashbash运行任何平台上使用。
mklement0

9

尝试删除双引号

grep --include=*.{html,php,htm} pattern -R /some/path

@tianyapiaozi尝试grep --include=\*.{html,php,htm} pattern -R /some/path。它为我工作。
Hyunjun Kim

4

这不行吗?

  grep pattern  /some/path/*.{html,php,htm} 

并不是的。这些文件可能位于子目录的子目录中
tianyapiaozi

2

试试这个。-r将进行递归搜索。-s将抑制文件未找到错误。-n将向您显示找到模式的文件的行号。

    grep "pattern" <path> -r -s -n --include=*.{c,cpp,C,h}

特别是这对我来说是最好的答案,我认为您可以放-rsn而不是-r -s -n(但这很挑剔)。
2016年

通常我使用-rns。为了使示例清楚,我不得不提到-r -n -s :-)很高兴它有所帮助。
Pradeep

我建议添加-I到标准集中。它跳过二进制文件(几乎从未搜索过),因此提高了效率。然后我们去grep -rIns ...声学效果很好的播放:)
血腥的

2

它具有相同的目的,但没有--include选择。它也适用于grep 2.5.1。

grep -v -E ".*\.(html|htm|php)"

0

grepfind命令一起使用

find /some/path -name '*.html' -o -name '*.htm' -o -name '*.php' -type f 
 -exec grep PATTERN {} \+

您也可以使用-regex-regextype选项。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.