【问题标题】:How do I recursively grep all directories and subdirectories?如何递归 grep 所有目录和子目录?
【发布时间】:2010-12-31 13:40:30
【问题描述】:

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

find . | xargs grep "texthere" *

【问题讨论】:

  • @TC1 可悲的是 grep 本身可以回答这个问题(至少 GNU grep): grep --help |grep recursive
  • 如果您发现自己经常使用 grep 进行递归搜索(尤其是如果您手动执行大量文件/目录排除),您可能会发现 ack(对程序员非常友好的 grep 替代方案)很有用.
  • 实际上,我在工作中使用的 Solaris 机器上既没有 -r 也没有 --recursive 工作。 grep 的手册页没有提到任何递归。我不得不自己寻找和 xargs。
  • ag 是我现在最喜欢的方式github.com/ggreer/the_silver_searcher
  • grep -rin xlsx *.pl 在 Redhat Linux 上对我不起作用。我收到“不匹配”错误。

标签: linux unix grep


【解决方案1】:
grep -r "texthere" .

第一个参数代表要搜索的正则表达式,第二个参数代表应该搜索的目录。在本例中,. 表示当前目录。

注意:这适用于 GNU grep,并且在 Solaris 等某些平台上,您必须专门使用 GNU grep 而不是旧版实现。对于 Solaris,这是 ggrep 命令。

【讨论】:

  • 注意:“grep -r”仅适用于较新的 grep。例如,它不适用于 AIX 5.3 附带的 grep。
  • 使用 grep -R 跟随符号链接。
  • 很高兴知道“-i”会使其不区分大小写,“-n”还包括每个匹配结果的行号。
  • 也很高兴知道,如果您只是在寻找固定字符串而不是正则表达式,请使用 -F 选项。通过不调用正则表达式解析器,它将为您节省大量时间。如果您要搜索大量文件,非常方便。
  • 别名 rgrep='grep -r'
【解决方案2】:

还有:

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

grep -r 是更好的答案。

【讨论】:

  • 或者,如果您不想担心文件名中的空格,find . -type f -exec grep "foo" '{}' \; 在受支持的情况下效果很好。
  • 如果您打算通过 xargs 将 find 通过管道传输到 grep,并且如果您只搜索固定字符串(即,不是正则表达式),您可能会从调用 grep -F 选项中受益,所以grep 不会为每次调用加载正则表达式引擎。如果有很多文件,它会更快。
  • 找到 . -type f -exec grep -Hu "foo" {} \;是我使用的,因为它给出了文件名。
  • 这适用于所有 *nix,因为它是 POSIX 7
  • find ./ -type f -print0 | xargs -0 grep "foo"
【解决方案3】:

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

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

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

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

【讨论】:

  • 适用于 Linux 和 Cygwin 附带的 grep,但不适用于 AIX 附带的 grep。
  • @KrzysztofWolny: ` ` 而不是 = 在 Ubuntu 上工作得很好。 PS:这应该是一个反引号的空格,但是 SO Markdown 解析器失败了。
  • @DanDascalescu 我赞成grep,而不是Ag,只是让你知道:)
  • 递归搜索时是否可以选择排除目录?
  • Windows cygwin 喜欢双引号 --include "*.txt" --include "*.TXT"
【解决方案4】:

只是文件名也很有用

grep -r -l "foo" .

【讨论】:

    【解决方案5】:

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

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

    (如 the comments 中的 kronen 所述,您可以添加 2>/dev/null 来取消权限拒绝输出)

    这包括以下选项:

    --include=PATTERN
    

    在目录中递归只搜索匹配PATTERN的文件。

    -n, --line-number
    

    在每行输出前加上输入文件中的行号。

    (注意:phuclvin the comments 添加到 -n decreases performance a lot so,因此您可能想跳过该选项)

    -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 实用程序更新。现在试试...
    • 这里最后一个字符*是什么意思?
    • @lorniper 它使 shell 选择您当前目录中的所有文件和文件夹,进而使 grep 应用于这些文件和(由于-R 选项递归)到文件夹。跨度>
    • @lorniper Noy 确切地说:*. 是一个 glob 模式(由 shell 解释):unix.stackexchange.com/a/64695/7490。 '.' 也会选择点文件或点文件夹(如.git/
    • 以前我一直使用grep -rnI,但后来我了解到-n decreases performance a lot,所以我只在真正需要时使用它,通常我会使用-rI
    【解决方案6】:

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

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

    SolarisHP-UX 同意。

    【讨论】:

    • {} \; 是什么意思-分别打印?
    • -exec选项中-符号{}是对find工具当前找到的文件名的引用(即对我们找到的文件名做一些事情),也是-exec选项应该以 ; 符号终止(以标记 exec 命令的结束),但是因为这一切都在 shell 中运行,所以符号应该被转义.. 最后 -print 选项让 find 工具打印出找到的文件名在屏幕上。
    【解决方案7】:

    这应该可行:

    grep -R "texthere" *
    

    【讨论】:

      【解决方案8】:

      注意find . -type f | xargs grep whatever这类解决方案在find匹配的文件太多时会遇到“Argument list to long”错误。

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

      【讨论】:

      • 嗯? xargs 专门解决“参数列表太长”问题。
      • 嗯,不 - xargs 专门用于将参数管道转换为 arglist,但是是的,现代 xargs 当与 -s 和/or -L 可以通过中断多个命令调用来处理非常长的参数列表,但默认情况下它没有这样配置(并且不在上述任何响应中)。例如:find . -type f | xargs -L 100 grep whatever
      • 那会在哪个平台上? POSIX xargs 已标准化为开箱即用。 xargs 实用程序应限制命令行长度,以便在调用命令行时,组合参数和环境列表...不应超过 {ARG_MAX}-2048 字节。”跨度>
      • 嗯。虽然在此基础上 gnu 文档不如 posix 清晰,并且我不再有权访问导致我发表此声明的机器,但我无法确认我对任何当前实现的原始解释。当然,如果可用,递归 grep 仍然是可取的,但没有什么理由避免使用 xargs 配方(请使用 -H 作为 grep 以避免最终调用 grep 只传递一个文件名)。
      【解决方案9】:

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

      这是一个简短的基准。我在每次测试前清除缓存(cf https://askubuntu.com/questions/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
      

      【讨论】:

        【解决方案10】:

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

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

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

        ./inc/xxxx_x.h

        2865: /** 描述 : stringYouWannaFind */

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

        【讨论】:

          【解决方案11】:

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

          grep -r texthere .|grep .txt

          【讨论】:

            【解决方案12】:

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

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

            请注意,-l(L 的小写)显示包含文本的文件的名称。如果您想打印匹配本身,请将其删除。或使用-H 将文件与匹配项一起获取。总之,其他选择是:

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

            -n 打印行号。

            【讨论】:

            • 投票赞成成为唯一的find 解决方案,以避免不必要地使用xargs 并使用+ 而不是\;-exec,从而避免大量不必要的进程启动. :-)
            【解决方案13】:
            The syntax is:
            cd /path/to/dir
            grep -r <"serch_word name"> .
            

            【讨论】:

            • 这并没有给其他答案增加太多
            【解决方案14】:

            要找到files 的名称,path 递归包含特定的string,请使用以下命令 对于UNIX

            find . | xargs grep "searched-string"
            

            对于Linux

            grep -r "searched-string" .
            

            UNIX 服务器上查找文件

            find . -type f -name file_name
            

            在 LINUX 服务器上查找文件

            find . -name file_name
            

            【讨论】:

              【解决方案15】:

              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
              

              替代方案

              ack(http://beyondgrep.com/)

              ag (http://github.com/ggreer/the_silver_searcher)

              【讨论】:

                【解决方案16】:

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

                对于UNIX 命令是:

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

                对于Linux 命令是:

                grep -r "string to be searched" .
                

                【讨论】:

                  【解决方案17】:

                  这是适用于我当前机器上的情况的一个(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"

                  【讨论】:

                    【解决方案18】:

                    如果你只想关注实际目录,而不是符号链接,

                    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" .
                    

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

                    /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) 非常有用,因此感谢您提出建议。
                    【解决方案19】:

                    我猜这就是你想要写的

                    grep myText $(find .)
                    

                    如果您想查找文件 grep hit

                    ,这可能会有所帮助
                    grep myText $(find .) | cut -d : -f 1 | sort | uniq
                    

                    【讨论】:

                    • 非常直观:例如:grep -i acc $(find . -name "execution*.*")
                    【解决方案20】:

                    这是一个递归(使用 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
                    

                    【讨论】:

                      【解决方案21】:

                      有关可用标志的列表:

                      grep --help 
                      

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

                      grep -rn "texthere" .
                      

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

                      grep -rni "texthere" /
                      

                      此处使用的标志:

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

                      【讨论】:

                        【解决方案22】:

                        在 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 上,这会安装 ripgrep: brew install ripgrep。这将安装silver-searcher:brew install the_silver_searcher

                        【讨论】:

                        • 如果您需要经常这样做,速度很重要,但我们大多数人发现自己一年最多只这样做几次。安装最新的漂亮的第三方 juju 工具 du jour 是多余的,而且自 1978 年以来没有太大变化的解决方案无论如何都值得了解。
                        • 我发现程序员每年只在源代码树中搜索几次文本是非常难以置信的。但即使从可用性的角度来看,rg 也比从头开始拼凑递归 grep 命令具有相当大的优势。使用rgrg foo。使用 unix 工具:find . | xargs grep foo。如果您的任何文件中包含引号,则需要使用find . -print0 | xargs -0 grep foo。如果您每年使用几次,您会记住这一点吗?
                        • 您忘记了find . -type f -exec grep 'regex' {} +,如果您经常使用这些工具,这确实很容易记住。但是,如果您需要经常查找内容,您可能应该在源代码树上运行 ctagsetags
                        • 我一直在使用 ripgrep,它很棒。但银牌搜索器对程序员来说非常棒。 +1
                        【解决方案23】:

                        globbing **

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

                        为了更实际的使用,这里是使用globbing syntax**)的语法:

                        grep "texthere" **/*.txt
                        

                        它仅对具有模式选择模式的特定文件进行 greps。它适用于支持的 shell,例如 Bash +4zsh

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

                        另见:How do I find all files containing specific text on Linux?

                        git grep

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

                        git grep "pattern"
                        

                        这样更快。

                        ripgrep

                        对于大型项目,最快的 grep 工具是 ripgrep,它默认递归地 grep 文件:

                        rg "pattern" .
                        

                        它建立在Rust's regex engine 之上,它使用有限自动机、SIMD 和积极的文字优化来加快搜索速度。检查detailed analysis here

                        【讨论】:

                        • 感谢 git grep 的建议——它非常有用,我不知道!
                        • 感谢 ripgrep 的建议。它的速度更快。
                        【解决方案24】:

                        把我的两分钱扔在这里。正如其他人已经提到的那样,grep -r 并不适用于所有平台。这可能听起来很傻,但我总是使用 git。

                        git grep "texthere"
                        

                        即使目录没有暂存,我也只是暂存它并使用git grep。

                        【讨论】:

                          【解决方案25】:

                          对于.gz文件,递归扫描所有文件和目录 更改文件类型或放 *

                          find . -name \*.gz -print0 | xargs -0 zgrep "STRING"
                          

                          【讨论】:

                            【解决方案26】:

                            另一种以递归方式在 Linux 系统上的所有文件中 grep 字符串的语法

                            grep -irn "string" /
                            

                            显示大量结果,因此您可能需要通过管道过滤输出

                            【讨论】:

                              猜你喜欢
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 2020-08-19
                              • 1970-01-01
                              • 2011-02-04
                              • 2015-09-19
                              • 1970-01-01
                              • 1970-01-01
                              相关资源
                              最近更新 更多