如何对目录中的所有文件执行grep操作?
Posted
技术标签:
【中文标题】如何对目录中的所有文件执行grep操作?【英文标题】:How to perform grep operation on all files in a directory? 【发布时间】:2013-02-23 13:57:18 【问题描述】:使用 xenserver,我想对目录中的每个文件执行命令,从命令的输出中提取一些内容并将其附加到文件中。
我很清楚我想使用的命令以及如何根据需要 grep 字符串。
但我不清楚的是如何让它对每个文件执行此命令,然后转到下一个文件,直到找不到更多文件。
【问题讨论】:
【参考方案1】:在 Linux 中,我通常使用此命令递归地 grep
获取目录中的特定文本:
grep -rni "string" *
在哪里
r
= 递归,即在当前目录中搜索子目录
n
= 将行号打印到stdout
i
= 不区分大小写的搜索
【讨论】:
【参考方案2】:要在所有子目录中搜索,但只能在特定文件类型中搜索,请使用 grep 和 --include
。
例如,在当前目录中递归搜索 *.yml 和 *.yaml 中的文本:
grep "text to search" -r . --include=*.yml,yaml
【讨论】:
【参考方案3】:如果你想执行多个命令,你可以使用:
for I in `ls *.sql`
do
grep "foo" $I >> foo.log
grep "bar" $I >> bar.log
done
【讨论】:
一般来说,可能在您发布的代码上尝试shellcheck.net。 Don't usels
to expand a wildcard(shell 已经为你做了!)和quote your shell variables。
您可能希望使用 Awk 来代替,尤其是在输入文件很大的情况下。 awk '/foo/ print >"foo.log" /bar/ print >"bar.log" ' "$I"
在输入文件中一次搜索两种模式。 (如果您想搜索多个模式,但不需要多个输出文件,请尝试grep -E 'foo|bar' "$I"
。)【参考方案4】:
使用查找。说真的,这是最好的方法,因为这样您就可以真正看到它正在操作的文件:
find . -name "*.sql" -exec grep -H "slow" \;
注意,-H 是特定于 mac 的,它会在结果中显示文件名。
【讨论】:
如果您决定使用 find,通过xargs
管道输出而不是使用-exec
,这将快得多,因为-exec
为每个 grep,并且大量文件的开销变得很大。关于文件名中空格的标准警告适用于xargs
。
这会是什么样子?我总是忘记xargs
语法。
@BrianPeterson 会是这样的:find . -iname "*.sql" -print0 | xargs -0 grep "slow"
grep -r
提供了几乎相同的功能。 OP 似乎实际上并不想遍历子目录。
-exec
在现代find
上支持快捷方式,就像xargs
一样,实际上会更快(因为你删掉了xargs
)。使用-exec ... +
而不是-exec ... \;
【参考方案5】:
grep $PATTERN *
就足够了。默认情况下,grep 会跳过所有子目录。但是,如果您想通过它们 grep,grep -r $PATTERN *
就是这种情况。
【讨论】:
"grep -r $PATTERN 。"足够了。对于递归 grep,您不需要指定所有文件 如何包含多个扩展?例如。 “*.cpp”、“*.h”? @Tomáš Zato,只需提供所有文件模式而不是 *:grep $PATTERN *.cpp *.h
。如果您需要更具体的规则来确定应该对哪些文件进行 grep,请使用 find
命令(查看 Rob 的答案)。
@Chris 您可能在当前目录中没有*.scss
文件,但在子目录更深处的某个位置,因此 grep 不会查看您想要的所有文件。您应该使用 --include
选项告诉 grep 递归查找与特定模式匹配的文件:grep -r x --include '*.scss' .
(请注意引号,它们会阻止 shell 扩展模式)。或者只使用find
(参见 Rob 的回答)。
您需要grep -s
,这样您就不会收到grep
跳过的每个子目录的警告。您可能应该在此处双引号 "$PATTERN"
。以上是关于如何对目录中的所有文件执行grep操作?的主要内容,如果未能解决你的问题,请参考以下文章
使用 grep/find 从整个目录和子目录文件中查找字符串 [关闭]