关于Linux:如何递归地grep?

How do I grep recursively?

如何递归地删除所有目录和子目录?

1
find . | xargs grep"texthere" *


1
grep -r"texthere" .

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

注意:这适用于GNUgrep,在某些平台(如Solaris)上,您必须特别使用GNUgrep,而不是传统的实现。对于Solaris,这是ggrep命令。


如果您知道您想要的文件的扩展名或模式,另一种方法是使用--include选项:

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

您还可以提到要用--exclude排除的文件。

如果您经常搜索代码,AG(Silver Searcher)是grep的一个更快的替代品,它是为搜索代码而定制的。例如,默认情况下,它是递归的,并自动忽略.gitignore中列出的文件和目录,因此您不必一直向grep或find传递同样麻烦的exclude选项。


也:

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

但江户十一〔二〕是一个更好的答案。


我现在总是使用(即使在Windows上使用gow--gnu):

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

包括以下选项:

1
--include=PATTERN

Recurse in directories only searching file matching PATTERN.

1
-n, --line-number

Prefix each line of output with the line number within its input file.

(注:phuclv在评论中补充说,-n大大降低了性能,因此您可能希望跳过该选项)

1
-R, -r, --recursive

Read all files under each directory, recursively; this is equivalent to the -d recurse option.

1
-H, --with-filename

Print the filename for each match.

1
-I

Process a binary file as if it did not contain matching data;
this is equivalent to the --binary-files=without-match option.

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

我可以得到:

1
2
3
4
5
6
7
8
/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;
...


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

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

SolarisHP-UX同意。


环球**

使用grep -r是可行的,但它可能会造成过度杀伤力,特别是在大文件夹中。

为了更实际的使用,下面是使用globbing语法(**的语法):

1
grep"texthere" **/*.txt

它只会用模式选择的模式跳过特定的文件。它适用于支持的外壳,如bash+4或zsh。

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

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

git grep

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

1
git grep"pattern"

这要快得多。

ripgrep

对于较大的项目,最快的grepping工具是ripgrep,默认情况下,它递归地对文件进行grepping:

1
rg"pattern" .

它建立在Rust的regex引擎之上,该引擎使用有限自动机、SIMD和积极的文字优化来快速搜索。在这里检查详细的分析。


使用下面的命令查找包含特定stringpath递归查找files的名称对于UNIX

1
find . | xargs grep"searched-string"

对于Linux

1
grep -r"searched-string" .

UNIX服务器上查找文件

1
find . -type f -name file_name

在Linux服务器上查找文件

1
find . -name file_name

只是文件名也很有用

1
grep -r -l"foo" .

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

1
grep -r"thingToBeFound" directory

如果您想遵循符号链接和实际目录(请注意无限递归)。

1
grep -R"thing to be found" directory

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

1
2
3
-H: outputs the filename with the line

-n: outputs the line number in the file

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

1
grep -rnH"Darth Vader" .

如果你想在目录中找到所有提到的单词cat

1
/home/adam/Desktop/TomAndJerry

你现在在目录里

1
/home/adam/Desktop/WorldDominationPlot

您希望捕获文件名,而不是字符串"cats"的任何实例的行号,并且希望递归遵循符号链接如果找到它们,您可以运行以下任意一个

1
2
3
grep -RH"cats" ../TomAndJerry                   #relative directory

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

来源:

运行"grep--help"

符号链接的简短介绍,对于任何阅读此答案并被我对它们的引用所迷惑的人:https://www.nixtutori.com/freebsd/understanding-symbolic-links/


ag是我现在最喜欢的方式github.com/ggreer/the_silver_searcher。它基本上与ACK相同,但还有一些优化。

这是一个简短的基准。我在每次测试前清除缓存(参见https://askubuntu.com/questions/155768/how-do-i-clean-or-disable-the-memory-cache)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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

如果要从目录结构中查找所有文件中的特定内容,可以使用find,因为您要做的更清楚:

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

注意,-l(l的小写)显示了包含文本的文件名。如果要打印匹配项本身,请将其删除。或者用-H把文件和匹配文件放在一起。总之,其他替代方案包括:

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

其中-n打印行号。


这是我在当前计算机(Windows7上的GitBash)上的案例:

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

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

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


这应该有效:

1
grep -R"texthere" *

grep -r"texthere" .(通知期结束)

(^学分:https://stackoverflow.com/a/1987928/1438029)

澄清:

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

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

GRP-递归

grep [options] PATTERN [FILE...]

[options]

-R, -r, --recursive

Read all files under each directory, recursively.

This is equivalent to the -d recurse or --directories=recurse option.

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

GRIP帮助

$ grep --help

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

选择

ack(http://beyondgrep.com/)

ag(http://github.com/ggreer/the ou silver_searcher)


下面是在UnixLinux环境中递归搜索String的命令。

对于Unix命令是:

1
find . -name"string to be searched" -exec grep"text""{}" \;

对于Linux命令是:

1
grep -r"string to be searched" .

在IBM AIX服务器(操作系统版本:AIX5.2)中,使用:

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

这将打印出文件中的路径/文件名和相对行号,如下所示:

/Inc/XXXXXX.H

2865:/**说明:StringYouwanNafind*/

不管怎样,它对我很有用:)


我想这就是你想写的

1
grep myText $(find .)

如果你想找到grep点击的文件,这可能是其他有用的东西。

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


有关可用标志的列表:

1
grep --help

返回当前目录中regexp文本的所有匹配项,对应的行号为:

1
grep -rn"texthere" .

返回文本的所有匹配项,从根目录开始,使用相应的行号并忽略大小写:

1
grep -rni"texthere" /

此处使用的标志:

  • -r递归
  • 带输出的-n打印行号
  • -i忽略案例

在2018年,您希望使用ripgrepthe-silver-searcher,因为它们比备选方案快得多。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
% 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


注意,当查找匹配的文件太多时,find . -type f | xargs grep whatever类解决方案会出现"参数列表到长"错误。

最好的选择是grep -r,但是如果没有,使用find . -type f -exec grep -H whatever {} \;


为了好玩,如果@christangrant answer太多而无法键入,可以快速而肮脏地搜索*.txt文件:-)

grep -r texthere .|grep .txt


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$ 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"

运行它和一个示例输出:

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

1
2
3
The syntax is:
cd /path/to/dir
grep -r <"serch_word name"> .