如何递归grep?


1682

如何递归grep所有目录和子目录?

find . | xargs grep "texthere" *

110
@ TC1可悲的是,grep本身可以回答问题(至少是GNU grep):grep --help | grep递归
Frank Schmitt

7
如果您发现自己经常使用grep进行递归搜索(尤其是如果您手动执行许多文件/目录排除),则可能会发现ack(对程序员非常友好的grep替代品)很有用。
Nick McCurdy 2013年

19
实际上,-r和--recursive都不在我使用的Solaris盒上工作。而且grep的手册页没有提及任何递归。我不得不求助于我,并发现自己。

8
ag是我现在最喜欢的方法,github.com
ggreer/

1
grep -rin xlsx *.pl在Redhat Linux上对我不起作用。我收到“不匹配”错误。
芦苇

Answers:


2507
grep -r "texthere" .

第一个参数表示要搜索的正则表达式,而第二个参数表示应搜索的目录。在这种情况下,.表示当前目录。

注意:这适用于GNU grep,在某些平台(如Solaris)上,必须专门使用GNU grep而不是传统实现。对于Solaris,这是ggrep命令。


39
注意:“ grep -r”仅适用于较新的版本。例如,它不适用于随附的grep AIX 5.3
2013年

110
使用grep -R跟随符号链接。
Eloff

53
很高兴知道“ -i”将使其不区分大小写,并且“ -n”还包括每个匹配结果的行号。
萨德,2015年

24
也很高兴知道,如果您只是在寻找固定的字符串而不是正则表达式,请使用-F选项。通过不调用正则表达式解析器,可以节省大量时间。如果要搜索大量文件,非常方便。
杰夫2015年

6
别名rgrep ='grep
-r'–

679

如果知道所需的文件扩展名或格式,则另一种方法是使用--includeoption:

grep -r --include "*.txt" texthere .

您也可以使用提及要排除的文件--exclude

如果您经常搜索代码,那么Ag(白银搜索器)是grep的更快选择,它是为搜索代码而定制的。例如,默认情况下它是递归的,并且会自动忽略中列出的文件和目录.gitignore,因此您不必一直将相同的繁琐排除选项传递给grep或find。


3
与Linux和Cygwin一起提供的grep一起使用非常好,但是与AIX一起提供的grep一起不能很好地工作。
2013年

1
@KrzysztofWolny:``而不是=在Ubuntu上很好用。PS:那应该是一个空白,但是SO Markdown解析器失败了。
Dan Dascalescu 2014年

4
@DanDascalescu我赞成,不赞成grepAg,请注意:)
Bernhard

1
在递归搜索时,我们是否可以选择排除目录?
汤姆·泰勒

Windows cygwin喜欢双引号--include "*.txt" --include "*.TXT"
Bob Stein

127

也:

find ./ -type f -print0 | xargs -0 grep "foo"

但这grep -r是一个更好的答案。


14
或者,如果您不想担心文件名中的空格,则find . -type f -exec grep "foo" '{}' \;在受支持的地方效果很好。
Edd Steel

4
如果要通过xargs将查找通过管道传递到grep,并且如果仅搜索固定字符串(即,不是正则表达式),则可能会受益于调用grep -F选项,因此grep将不会加载正则表达式引擎每次调用。如果有很多文件,它将更快。
杰夫

2
找 。-type f -exec grep -Hu“ foo” {} \; 是我使用的,因为它提供了文件名。
Wes

这适用于所有* nix,因为它是POSIX 7
Ciro Santilli冠状病毒审查六四事件法轮功

1
find ./ -type f -print0 | xargs -0 grep "foo"
aehlke 2014年

118

我现在总是使用(即使在带有GoW的 Windows上-Windows上的Gnu):

grep --include="*.xxx" -nRHI "my Text to grep" *

其中包括以下选项:

--include=PATTERN

在目录中递归,仅搜索文件匹配项PATTERN

-n, --line-number

在输出的每一行之前,在其输入文件中添加行号。

(注意:phuclv在注释中 添加会大大-n降低性能,因此,您可能要跳过该选项)

-R, -r, --recursive

递归读取每个目录下的所有文件;这等效于该-d recurse选项。

-H, --with-filename

打印每个匹配项的文件名。

-I     

处理二进制文件,就好像它不包含匹配的数据一样;
这等效于该--binary-files=without-match选项。

我可以添加' i'(-nRHIi如果需要不区分大小写的结果,)。

我可以得到:

/home/vonc/gitpoc/passenger/gitlist/github #grep --include="*.php" -nRHI "hidden" *
src/GitList/Application.php:43:            'git.hidden'      => $config->get('git', 'hidden') ? $config->get('git', 'hidden') : array(),
src/GitList/Provider/GitServiceProvider.php:21:            $options['hidden'] = $app['git.hidden'];
tests/InterfaceTest.php:32:        $options['hidden'] = array(self::$tmpdir . '/hiddenrepo');
vendor/klaussilveira/gitter/lib/Gitter/Client.php:20:    protected $hidden;
vendor/klaussilveira/gitter/lib/Gitter/Client.php:170:     * Get hidden repository list
vendor/klaussilveira/gitter/lib/Gitter/Client.php:176:        return $this->hidden;
...

Gow看起来很有前途-比我一直使用的GNU Windows实用程序新。立即尝试...
Radim Cernej '16

这里的最后一个字符*是什么意思?
lorniper '16

2
@lorniper使外壳程序选择当前目录中的所有文件和文件夹,从而使grep依次应用于那些文件和(由于该-R选项而递归地)应用于文件夹。
VonC

2
@lorniper Noy确切是:*还是.glob模式(由Shell解释):unix.stackexchange.com/a/64695/7490。' .'也将选择点文件或点文件夹(例如.git/
VonC

以前我一直使用,grep -rnI但是后来我了解到它会-n-rI
大大

25

在POSIX系统中,找不到的-r参数,grep并且grep -rn "stuff" .不会运行,但是如果使用find命令,它将:

find . -type f -exec grep -n "stuff" {} \; -print

商定SolarisHP-UX


的意义是什么 {} \; -分别打印?
user1169587 '16

3
-execoption中-symbol {}是对find工具当前找到的文件名的引用(即对我们找到的文件名进行处理),-execoption 也应该以;symbol 终止(以标记exec命令的结尾),但是因为这就是全部在shell中运行时,应将符号转义..最后,-print选项允许find工具在屏幕上打印出找到的文件名。
rook

19

环球 **

使用grep -r有效,但可能会过大,尤其是在大文件夹中。

为了更实际的使用,以下是使用通配语法**)的语法

grep "texthere" **/*.txt

仅抓取具有选定图案的图案的特定文件。它适用于受支持的shell,例如Bash +4zsh

要激活此功能,请运行:shopt -s globstar

另请参阅:如何在Linux上查找所有包含特定文本的文件?

git grep

对于受Git版本控制的项目,请使用:

git grep "pattern"

这要快得多。

ripgrep

对于大型项目,最快的ripgrepgrepping 工具是默认情况下以递归方式处理文件:

rg "pattern" .

它基于Rust的正则表达式引擎构建,该引擎使用有限自动机,SIMD和积极的文字优化来使搜索变得非常快。在此处检查详细分析


3
感谢git grep的建议-它非常有用,我不知道!
Basya

2
感谢ripgrep的建议。它的速度更快。
什么会酷

11

filespath递归方式包含的特定名称,请string使用以下命令UNIX

find . | xargs grep "searched-string"

Linux

grep -r "searched-string" .

UNIX服务器上查找文件

find . -type f -name file_name

在LINUX服务器上查找文件

find . -name file_name

11

只是文件名也可能有用

grep -r -l "foo" .

10

如果您只想遵循实际目录,而不是符号链接,

grep -r "thingToBeFound" directory

如果您想跟随符号链接以及实际目录(请注意无限递归),

grep -R "thing to be found" directory

由于您尝试递归grep,因此以下选项对您可能也很有用:

-H: outputs the filename with the line

-n: outputs the line number in the file

因此,如果要在当前目录或任何子目录中查找包含Darth Vader的所有文件并捕获文件名和行号,但是不希望递归遵循符号链接,则命令为

grep -rnH "Darth Vader" .

如果您想在目录中找到所有提及猫这个词

/home/adam/Desktop/TomAndJerry 

并且您当前在目录中

/home/adam/Desktop/WorldDominationPlot

并且要捕获文件名而不是字符串“ cats”的任何实例的行号,并且希望递归遵循符号链接(如果找到它们),则可以运行以下任一命令

grep -RH "cats" ../TomAndJerry                   #relative directory

grep -RH "cats" /home/adam/Desktop/TomAndJerry   #absolute directory

资源:

运行“ grep --help”

对符号链接的简短介绍,适用于阅读此答案并因我对其引用感到困惑的任何人:https : //www.nixtutor.com/freebsd/understanding-symbolic-links/


好答案。额外的开关(-rnh)很有帮助,因此感谢您的建议。
semtex41

8

现在,ag是我最喜欢的方法,github.com/ggreer/the_silver_searcher。它与ack基本相同,但还有更多优化。

这是一个简短的基准。我会在每次测试之前清除缓存(参阅/ubuntu/155768/how-do-i-clean-or-disable-the-memory-cache

ryan@3G08$ sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
3
ryan@3G08$ time grep -r "hey ya" .

real    0m9.458s
user    0m0.368s
sys 0m3.788s
ryan@3G08:$ sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
3
ryan@3G08$ time ack-grep "hey ya" .

real    0m6.296s
user    0m0.716s
sys 0m1.056s
ryan@3G08$ sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
3
ryan@3G08$ time ag "hey ya" .

real    0m5.641s
user    0m0.356s
sys 0m3.444s
ryan@3G08$ time ag "hey ya" . #test without first clearing cache

real    0m0.154s
user    0m0.224s
sys 0m0.172s


6

如果要从目录结构中查找所有文件中的特定内容,则可以使用find它,因为这样可以更清楚地了解正在执行的操作:

find -type f -exec grep -l "texthere" {} +

请注意-l(L的小写字母)显示了包含文本的文件的名称。如果您要打印匹配项本身,则将其删除。或用于-H将文件与匹配项一起获取。总之,其他替代方法是:

find -type f -exec grep -Hn "texthere" {} +

在哪里-n打印行号。


2
上投赞成票是唯一find既避免不必要使用的解决方案xargs和使用+,而不是\;-exec,从而避免不必要吨进程启动的。:-)
ShadowRanger

6

这是在我当前的机器上工作的案例(在Windows 7上为git bash):

find ./ -type f -iname "*.cs" -print0 | xargs -0 grep "content pattern"

我总是忘记带有空格的路径的-print0和-0。

编辑:我的首选工具现在改为ripgrep:https : //github.com/BurntSushi/ripgrep/releases。它确实非常快,并且具有更好的默认值(例如默认情况下为递归)。与我的原始答案相同的示例,但使用ripgrep:rg -g "*.cs" "content pattern"


4

grep -r "texthere" . (通知期末)

(^贷方:https : //stackoverflow.com/a/1987928/1438029


澄清:

grep -r "texthere" /(递归grep 所有目录和子目录)

grep -r "texthere" .(递归grep 这些目录和子目录)

grep递归

grep [options] PATTERN [FILE...]

[选项]

-R, -r, --recursive

递归读取每个目录下的所有文件。

这等效于-d recurse--directories=recurse选项。

http://linuxcommand.org/man_pages/grep1.html

grep帮助

$ grep --help

$ grep --help |grep recursive
  -r, --recursive           like --directories=recurse
  -R, --dereference-recursive

备择方案

ackhttp://beyondgrep.com/

aghttp://github.com/ggreer/the_silver_searcher


4

在2018年,您要使用ripgrepthe-silver-searcher因为它们比替代方法要快得多。

这是包含336个一级子目录的目录:

% find . -maxdepth 1 -type d | wc -l
     336

% time rg -w aggs -g '*.py'
...
rg -w aggs -g '*.py'  1.24s user 2.23s system 283% cpu 1.222 total

% time ag -w aggs -G '.*py$'
...
ag -w aggs -G '.*py$'  2.71s user 1.55s system 116% cpu 3.651 total

% time find ./ -type f -name '*.py' | xargs grep -w aggs
...
find ./ -type f -name '*.py'  1.34s user 5.68s system 32% cpu 21.329 total
xargs grep -w aggs  6.65s user 0.49s system 32% cpu 22.164 total

在OSX上,它将安装ripgrepbrew install ripgrep。安装silver-searcherbrew install the_silver_searcher


如果您需要经常这样做,速度很重要,但是我们大多数人发现自己一年最多只能这样做几次。安装最新的出色的第三方juju工具du jour实在是太过分了,无论如何,自1978年以来变化不大的解决方案都是令人高兴的。
Tripleee '18

我发现程序员每年只在源树中搜索文本几次是非常不现实的。但是即使从可用性的角度来看,rg与从头开始将递归grep命令整合在一起也具有相当大的优势。使用rgrg foo。使用UNIX工具:find . | xargs grep foo。并且,如果您的任何文件中都带有引号,则需要使用find . -print0 | xargs -0 grep foo。您是否还记得如果一年使用几次呢?
hughdbrown

1
您会忘记find . -type f -exec grep 'regex' {} +,如果定期使用这些工具,哪一个确实容易记住。但是,如果您需要经常查找内容,则无论如何应该运行ctagsetags在源代码树上运行。
Tripleee '18

我一直在使用ripgrep,它很棒。但是,对于程序员来说,银色搜索器是很棒的选择。+1
Matt

3

在我的IBM AIX Server(操作系统版本:AIX 5.2)中,使用:

find ./ -type f -print -exec grep -n -i "stringYouWannaFind" {} \; 

这将在文件中打印出路径/文件名和相对行号,例如:

./inc/xxxx_x.h

2865:/ **说明:stringYouWannaFind * /

无论如何,它对我有用:)



2

有关可用标志的列表:

grep --help 

返回当前目录中正则表达式文本的所有匹配项,并带有相应的行号:

grep -rn "texthere" .

从根目录开始,返回texthere的所有匹配,并带有相应的行号,并忽略大小写:

grep -rni "texthere" /

此处使用的标志:

  • -r 递归的
  • -n 输出行号
  • -i 忽略大小写

1

我想这就是你要写的

grep myText $(find .)

如果您想找到grep hit文件,这可能对您有所帮助

grep myText $(find .) | cut -d : -f 1 | sort | uniq

这非常直观:例如:grep -i acc $(find。-name“ execution *。*”)
Yu Yu

1

把我的两分钱丢在这里。正如其他人已经提到的,grep -r并非在所有平台上都适用。这听起来可能很愚蠢,但是我总是使用git。

git grep "texthere"

即使目录未暂存,我也可以暂存并使用git grep。


0

注意 find . -type f | xargs grep whatever当find匹配的文件过多时各种解决方案都将遇到“ Argument list to long”错误。

最好的选择是,grep -r但如果无法使用,请find . -type f -exec grep -H whatever {} \;改用。


?? xargs是“参数列表过长”问题的专门解决方法。
2015年

2
好吧,没有-xargs是专门用于将参数管道转换为arglist的,但是是的,的确,现代xargs 与-s和/或-L结合使用时,可以通过分成多个命令调用来处理很长的arglist,但是默认情况下,它不是通过这种方式配置的(并且上述任何响应中都没有)。例如:find . -type f | xargs -L 100 grep whatever
m.thome 2015年

那将在哪个平台上? POSIXxargs已标准化,可以立即使用。xargs实用程序应限制命令行的长度,以使在调用命令行时,组合的参数和环境列表……不得超过{ARG_MAX} -2048字节。”
2015年

嗯 在此基础上,虽然gnu文档不如posix清晰,并且我无法再使用使我发表此声明的机器,但我无法确认对任何当前实现的原始解释。递归grep当然还是比较可取的,但是如果有的话,它还是比较可取的,但是没有什么理由避免使用xargs配方(不过,请对grep使用-H来避免grep的最终调用仅传递一个文件名)。
m.thome 2015年

0

只是为了好玩,如果@christangrant答案太多而无法快速键入* .txt文件:-)

grep -r texthere .|grep .txt


0

这是一个递归函数(使用bash和sh进行了轻度测试),该函数遍历给定文件夹($ 1)的所有子文件夹,并grep在给定文件($ 2)中使用给定字符串($ 3)的搜索:

$ cat script.sh
#!/bin/sh

cd "$1"

loop () {
    for i in *
    do
        if [ -d "$i" ]
        then
            # echo entering "$i"
            cd "$i"
            loop "$1" "$2"
        fi
    done

    if [ -f "$1" ]
    then
        grep -l "$2" "$PWD/$1"
    fi

    cd ..
}

loop "$2" "$3"

运行它和示例输出:

$ sh script start_folder filename search_string
/home/james/start_folder/dir2/filename

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.