最好用例子来解释。
我可以:
find . -name "*.py" -type f > output.txt
但是如何将输出存储到同一文件中:
find . -name "*.py" -type f -exec grep "something" {} \
我不能只是做
find . -name "*.py" -type f -exec grep "something" {} \ > output.txt
答案1
如果我理解正确的话,这就是你想要做的:
find . -name '*.py' -print0 | xargs -0 grep 'something' > output.txt
查找所有具有扩展名的文件.py
,grep
仅包含包含行something
并将行保存在 中的行output.txt
。如果output.txt
文件存在,则将其截断,否则将创建该文件。
使用-exec
:
find . -name '*.py' -exec grep 'something' {} \; > output.txt
我在这里合并 Chris Downs 的评论:上述命令将导致grep
执行多次,以find
查找通过给定测试的路径名(仅上面的单个-name
测试)。但是,如果将 替换\;
为+
,grep
则会使用多个路径名find
(最多一定限制)进行调用。
查看问题在 find 中使用分号 (;) 与加号 (+) 与 exec 的比较有关该主题的更多信息。
答案2
如果您想保存 中所有文件的所有匹配行output.txt
,则最后一个命令确实有效,只是您缺少;
命令末尾所需的内容。
find . -name "*.py" -type f -exec grep "something" {} \; > output.txt
如果您希望每次运行都grep
将输出生成到不同的文件,请运行 shell 来计算输出文件名并执行重定向。
find . -name "*.py" -type f -exec sh -c 'grep "something" <"$0" >"$0.txt"' {} \;
答案3
根据记录,GNUgrep
有--include
和--exclude
参数,您可以使用它们来过滤它搜索的文件:
grep -r --include="*.py" "something" > output.txt
答案4
你问:
但是如何将输出存储到同一文件中:
find . -name "*.py" -type f -exec grep "something" {} \
你误会了。您无法将其传递给任何内容的原因是它不是完整的命令。结束语\
告诉您的 shell 继续读取下一行的命令,但这不是您打算在此处执行的操作。当你尝试时:
find . -name "*.py" -type f -exec grep "something" {} \ > output.txt
转义\
一个空白字符,因此,该字符将作为额外参数传递给find
,并且find
会抱怨传递给其选项的命令-exec
没有被终止。
必须通过添加+
or;
标记来终止该命令,并且该;
标记对于 shell 来说是特殊的,因此必须对其进行转义或引用。此外,{
和}
在大多数 shell 中也很特殊,因此也必须对它们进行转义或引用:
find . -name "*.py" -type f -exec grep "something" \{} \;
或者
find . -name "*.py" -type f -exec grep "something" '{}' ';'
这些是有效的命令,因此您可以很好地重定向和管道它们的输出:
find . -name "*.py" -type f -exec grep "something" \{} \; > output.txt
find . -name "*.py" -type f -exec grep "something" '{}' + | fgrep -v notthesefiles: > output.txt
顺便说一句,如果我不希望 shell 解释其中的任何字符,我更喜欢使用单引号参数,即使(正如 @Kusalananda 指出的那样),在这种情况下这是不必要的:
find . -name '*.py' -type f -exec grep 'something' \{} \; > output.txt
;
对于和之间的区别+
,请尝试man find
。