ChatGPT解决这个技术问题 Extra ChatGPT

我怎样才能递归地grep,但只能在具有某些扩展名的文件中?

我正在编写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.example

如何将结果限制在扩展程序 .h.cpp

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

S
Stephen Ostermiller

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

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

那应该做你想做的事。

从下面的 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
H
HoldOffHunger

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

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

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

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

grep:命令

-r:递归

-i:忽略大小写

--include: all *.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>,只要当前目录中没有与该模式匹配的文件。即,当您不使用 = 语法时,转义该模式是最安全的,但如果您假设当前目录中没有与该模式匹配的文件,您可能会很危险。
C
Community
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 选项,而不是其他选项?
@vladkras,你是什么意思针?是--吗?
几乎,但这对我不起作用——它一直在尝试匹配 --include=*.foo。可行的解决方案是将 --include 值用引号括起来。例如--include="*.foo"
P
Peter Mortensen

利用:

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})可能更可取。
P
Peter Mortensen

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

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

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


我遇到了几台网络托管公司的服务器,它们没有可用于 fgrep 的 --include 选项,这是我在这些实例中使用的命令行。
--include 选项在使用 Git for Windows (MinGW/MSys) 时也不可用。
@DarrenLewis 在适用于 Windows 的 Git Bash 中可用。但奇怪的是,它添加了像 ll 这样的彩色别名,但没有将 --color=auto 添加到 grep。
这应该是完整性、可移植性和简洁性的公认答案!
关于“HP 和 Sun 服务器”:您是指 HP-UXSolaris 吗?
S
Stephen Ostermiller

这个答案很好:

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

但它可以更新为:

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

这可以更简单。


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

由于这是查找文件的问题,让我们使用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}
#                      ^^^^^^^^^^^^^^^^^^^

如果 grep 命令匹配任何文件,我需要一个返回退出状态 1 的脚本。我开始使用 find+xargs+grep。但是,如果 grep 返回 1,xargs 返回退出状态 123 的事实使事情变得更加复杂。在我的情况下使用 grep 更简单。
P
Peter Mortensen

最简单的方法是:

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

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

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

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

P
Peter Mortensen

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_
P
Peter Mortensen

你应该为每个“-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”显示文件名和行。


P
Peter Mortensen

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

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

或者,如果您还需要行号:

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

n
nvd

如果你想从另一个命令的输出中过滤掉扩展,例如“git”:

files=$(git diff --name-only --diff-filter=d origin/master... | grep -E '\.cpp$|\.h$')

for file in $files; do
    echo "$file"
done