递归使用 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 <text-to-search-for>
)。结果是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的主要内容,如果未能解决你的问题,请参考以下文章