如何使用“ grep”命令查找包含子目录的文本


373

我想查找包含特定文本字符串的所有文件。该grep命令有效,但是我不知道如何在每个目录中使用它(我只能在当前目录中使用它)。我尝试阅读man grep,但没有任何帮助。


grep -RIn <您的模式> *将在所有文本文件中从当前目录向下搜索。不知道如何仅使用grep在* .C之类的文件模式中以递归方式进行搜索

1
--include="*.C"感谢@Lekensteyn,可使用通配符@ user311346。
鲍勃·斯坦

使用find和grep组合可递归地在文件中搜索当前目录和所有子目录中的字符串。检查此wilddiary.com/find-files- contains
Drona,

Answers:


487

最好使用

grep -rl "string" /path

哪里

  • -r(或--recursive)选项用于遍历的所有子目录/path,而
  • -l(或--files-with-matches)选项仅用于打印匹配文件的文件名,而不打印匹配的行(这也可以提高速度,因为grep使用此选项在第一次匹配时停止读取文件)。

13
实际上,如果“字符串”是要查找的文本模式,则最好使用该功能,否则当字符串包含点或特殊字符(在正则表达式中具有含义)而不仅仅是应该作为字符串找到的点时,有人可能会遇到问题。 ,原样。然后,我将使用“固定字符串”的-rlF开关-F(例如,不使用regexp)。当然,如果任务是使用正则表达式,请原谅。当然,同样的理论也没有-r,我经常看到人们假设grep搜索“文本”,这会引起一些问题,这些特殊问题意味着正则表达式。
LGB

4
还有-i一个忽略大小写的标志。
Marco Ceppi

3
我只想展示该--recursive选项,有很多可以谈论的选项和使用场景。我从@dmityugov接受的答案开始,并修改为不使用find
enzotib 2011年

1
@NN:完成:-)
enzotib 2011年

3
@ScottBiggs:带有选项--include '*.h'
enzotib

167

如果要查找文件中匹配的行,我最喜欢的命令是:

grep -Hrn 'search term' path/to/files
  • -H 导致打印文件名(搜索多个文件时隐含)
  • -r 进行递归搜索
  • -n 使行号被打印

path/to/files可以.在当前目录中搜索

我认为其他有用的其他选项:

  • -I忽略二进制文件(补充:-a将所有文件视为文本)
  • -F治疗search term为文字,而不是一个正则表达式
  • -i 进行不区分大小写的搜索
  • --color=always即使通过管道也强制颜色less。要制作less支持色,您需要使用以下-r选项:

    grep -Hrn search . | less -r
    
  • --exclude-dir=dir用于排除目录,如.svn.git

输出示例


13
-H如果可能的话,一个文件夹上的文件是多余的(如果有多个文件)。实际上,手册页上说-H, --with-filename: Print the file name for each match. This is the default when there is more than one file to search.
enzotib 2011年

我不知道,它总是按我预期的那样工作。查找文件时这是我的默认命令。
Lekensteyn

1
有没有办法只考虑扩展名为.a的文件(并将其与-r结合使用)?
user2413 2012年

6
@ user2413试试--include '*.*'
Lekensteyn 2012年

1
@alper Trygrep --exclude='*~' ...
Lekensteyn

24

我相信您可以使用以下方式:

find /path -type f -exec grep -l "string" {} \;

评论说明

find是一个命令,可让您在给定路径的子目录中查找文件和其他对象,例如目录和链接。如果您没有指定文件名应满足的掩码,它将枚举所有目录对象。

  • -type f 指定仅处理文件,不处理目录等。
  • -exec grep指定对于每个找到的文件,它应运行grep命令,并将其文件名作为参数传递给它,方法是替换{}为文件名

3
仅对于那些不知道的人,添加-name '*.py'限制将匹配项限制为以'.py'结尾的文件。
丹尼尔·F

我喜欢这涵盖了在其grep命令中未实现-R的客户端。
Aviose 2014年

如果要打印匹配的行和文件名,请使exec像这样:... -exec bash -c 'grep -r "mystring" {} && echo {}' \;
Donn Lee

直接使用grep的相对性能是多少?
乔纳森

19

我的默认命令是

grep -Rin string *

我使用国会大厦“ R”,因为ls将其用于递归。由于grep接受两者,因此没有理由不使用它。

编辑:根据HVNSweeting,显然-R将遵循符号链接,而-r不会。


1
要也搜索隐藏文件,请运行shopt -s dotglob(记住-s为“ set”)。然后删除文件时要小心。如果你dotglob启用,rm -r *将删除当前目录中的一切,但目录上面,因为..匹配。要禁用dotglob,请使用shopt -u dotglob(“取消设置”)。尽管更改是暂时的,但仅适用于当前shell。
Lekensteyn 2011年

我忘记了这一点。有没有一种方法可以将其设置为一行?像shopt -s dotglob & <grep cmd> & shopt -y dotglob只是更方便的东西?这样,我们就不必担心对其进行重置
user606723,2011年

同样,grep -Rin string .在大多数情况下使用起来可能更容易。我只使用*,因为它看起来更自然。
2011年

1
如果您执行递归grep,则可以从“”开始。代替 ”*”。无需dotglob。
米哈尔Šrajer

1
对此进行投票,在联机帮助页中没有提及的一件事是R将遵循符号链接,r而不是
HVNSweeting

12

如果您愿意尝试新的东西,请尝试一下ack。递归搜索当前目录的命令string是:

ack string

安装非常简单:

curl http://betterthangrep.com/ack-standalone > ~/bin/ack && chmod 0755 !#:3

(前提是您已经有了目录~/bin,并且最好在您的目录中PATH。)


2
或者只是apt-get install ack-grep(并在您的.bashrc中添加别名ack = ack-grep)
markijbema 2011年

chmod命令的最后一个参数做什么?它们是专用chmod还是与bash相关(!#:3一部分)?
Elliott Darfink 2014年

@ElliottDarfink使用Bash的历史记录功能!事件指示符。它们非常强大,可以避免重复。!#:3到目前为止,引用命令行的第三个标记,即~/bin/ack在这种情况下。
康拉德·鲁道夫

4

rgrep命令专用于此类需求

如果不可用,您可以像这样获得它

mkdir -p ~/bin
cd ~/bin
wget http://sdjf.esmartdesign.com/files/rgrep
chmod +x rgrep

您可以如上所述直接设置默认grep选项。

我个人使用

[[  ${#args} -lt 5 && "${args//[[:space:]]/}" == "-i" ]] && args="-Hin"
args="${args:--Hns} --color=auto"

相关主题:如何始终将rgrep与颜色配合使用


rgrep由grep软件包提供,该软件包默认安装在Ubuntu中。
karel 2015年

2

更新2:

这行命令使用findgrep解决了该问题:

$ find path_to_search_in -type f -exec grep -in searchString {} 2> /dev/null +

--color=<always or auto> 对于彩色输出:

$ find path_to_search_in -type f \
            -exec grep --color=always -in searchString {} 2>/dev/null +

例:

$ find /tmp/test/ -type f -exec grep --color=auto -in "Search string" {} 2>/dev/null +

在以下快照中运行的示例: 快照1


更新1:

您可以尝试以下代码;作为您.bashrc.bash_aliases脚本中的函数:

wherein () 
{ 
    for i in $(find "$1" -type f 2> /dev/null);
    do
        if grep --color=auto -i "$2" "$i" 2> /dev/null; then
            echo -e "\033[0;32mFound in: $i \033[0m\n";
        fi;
    done
}

用法: wherein /path/to/search/in/ searchkeyword

例:

$ wherein ~/Documents/ "hello world"

(注意:如@enzotib在下面的注释中所建议,此方法不适用于文件/目录,包括名称中的空格。)


原始帖子

要搜索字符串并仅输出带有搜索字符串的那一行:

$ for i in $(find /path/of/target/directory -type f); do \
    grep -i "the string to look for" "$i"; done

例如:

$ for i in $(find /usr/share/applications -type f); \
    do grep -i "web browser" "$i"; done

要显示包含搜索字符串的文件名:

$ for i in $(find /path/of/target/directory -type f); do \
    if grep -i "the string to look for" "$i" > /dev/null; then echo "$i"; fi; done;

例如:

$ for i in $(find /usr/share/applications -type f); \
    do if grep -i "web browser" "$i" > /dev/null; then echo "$i"; \
    fi; done;

包含空格的文件名失败。没有显示stderr的事实掩盖了失败。
enzotib

@enzotib感谢您指出这一点..对于指定的功能来说仍然无法解决..不过我添加了另一种衬里..
2015年

现在答案类似于@dmityugov。
enzotib 2015年

是的,但是从这个意义上讲,如果您检查的话,此页面上的大多数答案在使用方式上都是相似的grep,其次是使用... 的子集findgrep但是如果您要接受不同的开关和调整作为唯一的答案,可能我的也适合这里..还是您与众不同?最后一次更新符合我在搜索中的要求:文件名带有搜索键的行和行号。:),彩色输出和错误过滤器,以提高可读性
精确到

2

grepGNUBSD

您可以使用该grep工具通过-r参数递归搜索当前文件夹,例如:

grep -r "pattern" .

注意:-r-递归搜索子目录。

要在特定文件中搜索,可以使用以下语法

grep "class foo" **/*.c

注意:通过使用globlob选项**),它将以特定的扩展名或模式递归扫描所有文件。要启用此语法,请运行:shopt -s globstar您也可以使用**/*.*所有文件(不包括隐藏文件和不带扩展名的文件)或任何其他模式。

如果您发现参数过长的错误,请考虑缩小搜索范围,或改用如下find语法:

find . -name "*.php" -execdir grep -nH --color=auto foo {} ';'

或者使用ripgrep

ripgrep

如果您正在处理较大的项目或大文件,则应ripgrep改用,例如:

rg "pattern" .

GitHub项目页面上签出文档,安装步骤或源代码。

它比其他工具一样快多了GNU / BSD grepucgagsiftackpt或类似的,因为它是建立在之上锈病的正则表达式引擎,它使用有限自动机,SIMD和积极文字的优化,使搜索速度非常快。

它支持.gitignore文件中指定的忽略模式,因此单个文件路径可以同时与多个glob模式匹配。


您可以使用常见参数,例如:

  • -i -不敏感的搜索。
  • -I -忽略二进制文件。
  • -w -搜索整个单词(与部分单词匹配相反)。
  • -n -显示您的比赛路线。
  • -C/ --context(例如-C5)-增加上下文,因此您会看到周围的代码。
  • --color=auto -标记匹配的文本。
  • -H -显示找到文本的文件名。
  • -c-显示匹配行数。可以结合使用-H

1

我使用xargs执行此操作,这是一个非常低估的命令

find ./ -type f -print0 | xargs -0 grep 'string_you_are_looking_for'

查找./为您提供当前文件夹中所有文件的递归列表,然后将其通过管道传递给xargs,该xargs在每个文件中执行grep命令


4
xargs不建议不使用 with -print0选项find和to -0选项xargs,它将对包含空格的文件名失败。
enzotib 2011年

@enzotib我已经按照您的建议编辑了答案。-请仔细阅读,如果需要编辑和更正,我将很乐意由您重新编辑。谢谢
αғsнιη

1
@KasiyA:现在可以,删除我的否决票。
enzotib

0

我知道这里有很多答案,但是如果您想在搜索文件时添加其他限制,可以使用以下替代方法:

find . -type f -exec grep --quiet string_to_look_for {} ';' -print

之所以有效,是因为grep如果找到结果将返回0,否则返回1。例如,您可以找到1 MB大的文件其中包含以下内容:

find . -type f -exec grep --quiet string_to_look_for {} ';' -size 1M -print

对于多种需求,您可能要使用-OGNU grep中存在的优化器标志。


0

用于搜索C,CPP代码的脚本(查找代码):

#!/bin/sh

find . \( -iname "*.c" -o -iname "*.cpp" -o -iname "*.h" \) -type f -print0 | xargs -0 grep --color -n "$1"

采用:

find-in-code "search string"
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.