【问题标题】:How can I grep recursively, but only in files with certain extensions?我怎样才能递归地grep,但只能在具有某些扩展名的文件中?
【发布时间】:2012-09-13 01:46:27
【问题描述】:

我正在编写指向grep 某些目录的脚本:

{ grep -r -i CP_Image ~/path1/;
grep -r -i CP_Image ~/path2/;
grep -r -i CP_Image ~/path3/;
grep -r -i CP_Image ~/path4/;
grep -r -i CP_Image ~/path5/; }
| mailx -s GREP email@domain.com

如何将结果限制为仅扩展 .h.cpp

【问题讨论】:

  • 试过grep -r -i CP_Image ~/path1/*.{h,cpp}?
  • 使用The Silver Searcher:ag -i CP_Image ~/path[1-5] | mailx -s GREP email@domain.com。工作完成。
  • 使用 egrep(很可能预装在您的系统上),然后您可以使用正则表达式。
  • 当 GNU 家伙将 -r 添加到 grep 以使其搜索文件时,他们真的搞砸了,因为这打破了 UNIX 拥有“做一件事并做好”工具的口头禅。有一个非常好的工具可以查找名称非常明显的文件。

标签: grep


【解决方案1】:

只需使用--include 参数,如下所示:

grep -inr --include \*.h --include \*.cpp CP_Image ~/path[12345] | mailx -s GREP email@domain.com

这应该可以满足您的需求。

以下HoldOffHunger's answer的解释:

  • grep:命令

  • -r:递归

  • -i: 忽略大小写

  • -n: 每个输出行前面都有它在文件中的相对行号

  • --include \*.cpp: 所有 *.cpp: C++ 文件(使用 \ 转义,以防万一您的目录中文件名中带有星号)

  • ./:从当前目录开始。

【讨论】:

  • 记录:-r(递归)-i(忽略大小写)--include(仅搜索与文件模式匹配的文件)
  • 可以进一步优化为grep -r -i --include \*.h --include \*.cpp CP_Image ~/path[12345]
  • @Hong -R 用于符号链接的文档在哪里?
  • 这个例子似乎得分很高,因为它涵盖了如此广泛的可能性,但下面给出的答案 grep -r --include=*.txt 'searchterm' ./ 真正解释了本质答案
  • 为什么不用双引号代替反斜杠呢?例如:grep -r -i --include="*.h" --include="*.cpp" CP_Image
【解决方案2】:

其中一些答案似乎过于繁琐,或者它们在我的 Debian 服务器上产生了问题。这对我来说非常有效:

grep -r --include=\*.txt 'searchterm' ./

...或不区分大小写的版本...

grep -r -i --include=\*.txt 'searchterm' ./
  • grep:命令

  • -r:递归

  • -i: 忽略大小写

  • --include: 所有 *.txt: 文本文件(用 \ 转义,以防万一你有一个文件名中带有星号的目录)

  • 'searchterm': 搜索什么

  • ./:从当前目录开始。

来源:PHP Revolution: How to Grep files in Linux, but only certain file extensions?

【讨论】:

  • 您应该使用\*.cpp'*.cpp' 转义*。否则当工作目录包含一些*.txt 文件时,它不会给出预期的结果。
  • @Melebius 你能解释一下为什么它需要转义 - 它与你提到的 CPP 或 TXT 扩展有什么关系吗?还是您只是将这些用作示例?
  • @SimonEast 这些扩展是本问答中使用的扩展,除此之外没有什么特别之处。使用--include=<pattern> 时它可能无需转义即可工作,但重要的是使用--include <pattern>(空格而不是=)转义*,否则感觉非常相似。
  • @Melebius 添加到您所写的内容中,它确实适用于 --include=<pattern>。它也适用于--include<pattern>,只要当前目录中没有与该模式匹配的文件。也就是说,当您不使用 = 语法时,最安全的方式是转义该模式,但如果您假设当前目录中没有与该模式匹配的文件,您可能会面临危险。
【解决方案3】:
grep -rnw "some thing to grep" --include=*.{module,inc,php,js,css,html,htm} ./

【讨论】:

  • grep -rn "需要 grep 的东西" --include=*.{module,inc,c,h} *
  • 不错的答案。比 IMO 上接受的更干净,但您应该添加搜索条件,如 @ashish 所述
  • 为什么是--include选项在needle之后,而不是其他选项?
  • @vladkras,针是什么意思?是--吗?
  • 几乎,但这对我不起作用——它一直试图匹配--include=*.foo。可行的解决方案是将 --include 值用引号括起来。例如。 --include="*.foo".
【解决方案4】:

用途:

find . -name '*.h' -o -name '*.cpp' -exec grep "CP_Image" {} \; -print

【讨论】:

  • 我建议将这些 -name 参数分组。如果您不这样做,可能会发生奇怪的事情。 find . \( -name '*.h' -o -name '*.cpp' \) -exec grep "CP_Image" {} \; -print
  • 与附加的“-type f”一起使用以忽略所有目录对象,只对文件感兴趣。
  • 我多年来一直使用这种方法并且它有效,但它比递归 grep 慢很多,因为 find 的 exec 为每个要搜索的文件生成一个单独的 grep 进程。
  • 针对@beaudet 的评论,find 可以选择捆绑参数,将被调用进程的调用减少到最低限度。 find . \( -name \*.h -o -name \*.cpp \) -exec grep -H CP_Image {} + 这是建议但未在下面@fedorqui 的答案中突出显示,这是一个值得改进的地方。当 find 仅标识单个匹配文件时,此处 grep 的 -H 参数很有用。这可以消除答案中-print 的使用。如果您的文件总列表足够小,则使用递归 shell glob(例如{path1,path2}/**/*.{cpp,h})可能会更好。
【解决方案5】:

在 HP 和 Sun 服务器上没有任何 -r 选项,但这种方式在我的 HP 服务器上对我有用:

find . -name "*.c" | xargs grep -i "my great text"

-i 用于不区分大小写的字符串搜索。

【讨论】:

  • 我遇到过几台网络托管公司的服务器,它们没有可用于 fgrep 的 --include 选项,这是我在这些实例中使用的命令行。
  • 使用 Git for Windows (MinGW/MSys) 时 --include 选项也不可用。
  • @DarrenLewis 在适用于 Windows 的 Git Bash 中可用。但奇怪的是,它添加了像ll 这样的彩色别名,但没有在grep 中添加--color=auto
  • 这应该是完整性、可移植性和简洁性的公认答案!
  • Re "HP 和 Sun 服务器":你的意思是 HP-UXSolaris
【解决方案6】:

由于这是查找文件的问题,我们使用find

使用 GNU find 您可以使用-regex 选项在目录树中查找扩展名为.h.cpp 的文件:

find -type f -regex ".*\.\(h\|cpp\)"
#            ^^^^^^^^^^^^^^^^^^^^^^^

然后,只需对其每个结果执行grep

find -type f -regex ".*\.\(h\|cpp\)" -exec grep "your pattern" {} +

如果你没有这个 find 分布,你必须使用Amir Afghani's 之类的方法,使用-o 连接选项(名称以.h.cpp 结尾):

find -type f \( -name '*.h' -o -name '*.cpp' \) -exec grep "your pattern" {} +
#            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

如果你真的想使用grep,请按照--include指示的语法:

grep "your pattern" -r --include=*.{cpp,h}
#                      ^^^^^^^^^^^^^^^^^^^

【讨论】:

    【解决方案7】:

    最简单的方法是:

    find . -type  f -name '*.extension' 2>/dev/null | xargs grep -i string
    

    添加2>/dev/null 以终止错误输出。

    在整个系统中包含更多文件扩展名和密码:

    find / -type  f \( -name '*.conf' -o -name "*.log" -o -name "*.bak" \) 2>/dev/null |
    xargs grep -i password
    

    【讨论】:

      【解决方案8】:

      这个答案很好:

      grep -r -i --include \*.h --include \*.cpp CP_Image ~/path[12345] | mailx -s GREP email@domain.com
      

      但可以更新为:

      grep -r -i --include \*.{h,cpp} CP_Image ~/path[12345] | mailx -s GREP email@domain.com
      

      这可以更简单。

      【讨论】:

      • “下面的答案”指的是什么?对答案的相对位置的引用是不可靠的,因为它们取决于视图(投票/最旧/活动)和已接受答案的变化以及随时间的变化(投票、活动和接受状态)。请通过editing your answer 回复,而不是在 cmets 中(without "Edit:"、"Update:" 或类似的 - 答案应该看起来像是今天写的)。
      • 我们可以简单地使用 grep 命令和 ls 命令吗?
      • @Harsha 当然。使用管道将 ls 的输出作为 grep 的输入。比如ls | grep *.h
      • 您能否提供一个链接来解释我如何才能完全理解这一点?
      【解决方案9】:

      ag(银色搜索者)的语法非常简单

             -G --file-search-regex PATTERN
                Only search files whose names match PATTERN.
      

      所以

      ag -G *.h -G *.cpp CP_Image <path>
      

      【讨论】:

      • 使用 ag 2.2.0,我需要把我的标志放在最后:ag _string_to_find_ -G _filename_regex_
      【解决方案10】:

      你应该为每个“-o -name”写“-exec grep”:

      find . -name '*.h' -exec grep -Hn "CP_Image" {} \; -o -name '*.cpp' -exec grep -Hn "CP_Image" {} \;
      

      或按 ( ) 分组

      find . \( -name '*.h' -o -name '*.cpp' \) -exec grep -Hn "CP_Image" {} \;
      

      选项'-Hn'显示文件名和行。

      【讨论】:

        【解决方案11】:

        这是我通常用来查找 .c.h 文件的方法:

        tree -if | grep \\.[ch]\\b | xargs -n 1 grep -H "#include"
        

        或者如果您还需要行号:

        tree -if | grep \\.[ch]\\b | xargs -n 1 grep -nH "#include"
        

        【讨论】:

          【解决方案12】:

          如果您想从另一个命令的输出中过滤掉扩展名,例如“混帐”:

          files=$(git diff --name-only --diff-filter=d origin/master... | grep -E '\.cpp$|\.h$')
          
          for file in $files; do
              echo "$file"
          done
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2010-11-14
            • 2019-01-01
            • 1970-01-01
            • 2013-08-18
            • 2011-08-24
            • 2014-01-05
            • 1970-01-01
            相关资源
            最近更新 更多