递归使用 grep

Posted

技术标签:

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

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

【问题讨论】:

您想要执行以下操作:find /path/to/find -name "nameofthefile" 还是想要对每个文件进行分类以检查字符串? 【参考方案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,但我不明白将输出通过管道传输到不同的命令有何意义。无论如何,我正在尝试您的解决方案,很快就会接受您的回答。

以上是关于递归使用 grep的主要内容,如果未能解决你的问题,请参考以下文章

使用grep和sed递归查找和替换所有文件中的字符串[重复]

sh 如何使用grep和ack递归搜索文件夹中的字符串

Linux递归压缩图片脚本

grep 递归查找 Linux 上的特定文件类型

linux命令---grep命令使用

使用 grep 时获取行号