【问题标题】:Using grep recursively递归使用 grep
【发布时间】:2013-02-16 13:14:23
【问题描述】:

grep 可以使用-r 选项进行递归搜索。但是,我想知道 grep 是否能够递归地搜索指定数量的子文件夹级别的查询字符串。例如,我有一个文件夹 root,其中包含文件夹 parent1, parent2, ..., parentN。每个父文件夹都有普通的文本文件和名为child1, child2, ..., childM 的文件夹。我想从根级别运行 grep 并在父母内部的文件中搜索而不查看子文件夹。有没有简单的方法来做到这一点?

【问题讨论】:

  • 您想要执行以下操作:find /path/to/find -name "nameofthefile" 还是想要对每个文件进行分类以检查字符串?

标签: search full-text-search grep cygwin


【解决方案1】:

作为Kentnotes,你不能用一个直的grep来做这个;它根本不够强大。诀窍是使用find 确定要搜索的文件,并将find 生成的文件列表传递给grep

如果您运行man find,您将获得find 采用的许多 选项的手册页。我们在这里感兴趣的是-maxdepth

让我们构建我们需要的命令。在每个阶段运行命令以查看它的样子:

  • find . 将列出当前文件夹 (.) 或任何后代文件夹中存在的所有文件和文件夹。

  • find . -maxdepth 1 将列出当前文件夹中的所有文件和文件夹。 find . -maxdepth 2 同样会列出当前文件夹和任何直接子文件夹中的所有文件和文件夹。等等……

  • 请注意,我们也会列出文件夹;我们不希望这样,因为grep 不能搜索文件夹本身,只能搜索文件夹中的文件。添加-type f 以仅获取列出的文件:find . -maxdepth 2 -type f

现在我们知道了要搜索的文件,我们需要获取grep 来搜索这些文件。执行此操作的标准方法是使用 xargs:

find . -maxdepth 2 -type f | xargs grep <text-to-search-for>

|find(即您通常在屏幕上看到的内容)获取“标准输出”,也就是“stdout”,并将其通过管道传输到xarg 的“标准输入”,也就是“stdin”,即,如果您正在输入正在运行的程序,通常会发生什么。

xargs 是一个狡猾的小程序,在添加它在标准输入上收到的所有参数后,它会运行你告诉它的任何东西(这里是grep &lt;text-to-search-for&gt;)。结果是grep 将搜索find 找到的每个文件。

但是,如果您的某些文件名中有空格,这将不起作用,因为xargs 认为空格分隔两个不同的文件名,而不是一个文件名的一部分。有很多方法可以解决这个问题(理想的方法是不要在文件名中使用空格),最常见的方法是使用 find 的一个更高级的功能。

如果您将-exec 参数添加到find,它将执行您指定的所有内容,直到;+。如果您添加 {}(即文字字符 {}),它将用所有文件的列表替换它。由于find 正在这样做,它知道文件名中的空格应该在文件名中。

因此,做你想做的事情的最好方法是:

find . -type f -maxdepth 2 -exec grep <text-to-search-for> {} +

(+; 结尾的区别在这里没有区别。如果你有兴趣,可以在man find,但简短的版本是+ 更快,但意味着你只能有一个{} 在命令中。)

【讨论】:

    【解决方案2】:

    你可以试试这些:

    grep

     --exclude=GLOB
                  Skip files whose base name matches GLOB  (using
                  wildcard  matching).   A file-name  glob  can  use *,
                  ?, and [...]  as wildcards, and \ to quote a wildcard
                  or backslash character literally.
    
           --exclude-from=FILE
                  Skip files whose base name matches any of the file-name
                  globs  read  from FILE (using wildcard matching as
                  described under --exclude).
    
           --exclude-dir=DIR
                  Exclude directories matching the pattern DIR from
                  recursive searches.
    

    或使用此find | xargs grep

    使用查找,您可以定义级别

    编辑

    一个命令到另一个命令的管道输出在 linux/unix 世界中很常见。我敢打赌你每天都这样做。

    echo "abc"|sed 's/a/x/'
    find . -name "*.pyc" |xargs rm
    awk 'blahblah' file | sort |head -n2 
    tree|grep 'foo'
    mvn compile|ack 'error'
    ...
    

    请注意,并非所有上述示例都是有效的。它们只是示例。

    【讨论】:

    • 感谢您的快速回答。你能解释一下是什么吗?在你的例子中表示。我知道它可用于将输出通过管道传输到 dest,但我不明白将输出通过管道传输到不同的命令有何意义。无论如何,我正在尝试您的解决方案,很快就会接受您的回答。
    猜你喜欢
    • 1970-01-01
    • 2010-10-27
    • 1970-01-01
    • 1970-01-01
    • 2010-10-16
    • 1970-01-01
    • 2010-11-10
    • 1970-01-01
    • 2014-02-05
    相关资源
    最近更新 更多