find
使用选项传递组合命令的有效语法是什么-exec
?
例子:
find . -type f -name "*.txt" -exec grep FirstKeyWord {} | grep SecondKeyWord \;
失败并显示以下错误消息:
find: grep: missing argument to `-exec`
;: No such file or directory
&&
当使用或;
而不是 来组合命令时,也会出现同样的失败|
。我甚至尝试使用 ' 或 $() 或 {} 等来引用组合命令,但失败了(很不幸)。
注意:我正在寻找一个不使用自定义脚本的单行解决方案。
答案1
您可以通过在 exec 中明确调用 shell 来在参数中使用复杂的 shell 命令。
find . -type f -name "*.txt" -exec sh -c 'grep FirstKeyWord "$1" | grep SecondKeyWord' -- {} \;
这将使用sh
为每个文件提供的命令列表来执行,并传递文件名$1
。
编辑:OP 指出这有效并且更简单:
find . -type f -name "*.txt" -exec sh -c 'grep FirstKeyWord {} | grep SecondKeyWord' \;
答案2
对于您的具体示例,您可以这样做:
find . -type f -name "*.txt" -exec grep FirstKeyWord {} \; | grep "SecondKeyWord"
顺便说一句,这也可以不使用第二个 grep 来完成。相反,使用following by或following byegrep
这两个替代方案:FirstKeyWord
SecondKeyWord
SecondKeyWord
FirstKeyWord
find . -type f -name "*.txt" -exec egrep "FirstKeyWord.*SecondKeyWord|SecondKeyWord.*FirstKeyWord" {} \;
如果您可以对结果路径名做出一些保证find
(例如路径名中没有前导或内部空格并且没有换行符),那么您也可以这样做:
find . -type f -name "*.txt" -print | while read filename; do grep "FirstKeyWord" "${filename}" | grep "SecondKeyWord"; done
更普遍的答案是“你不能”直接从find
。管道命令或使用&&
或是||
shell 的功能,而不是执行进程的功能。
我以前使用过这种模式,但是它很脆弱而且比较复杂:
find . -type f -name "*.txt" -print \
| sed -e 's;[\\$"`!];\\&;g' \
-e 's;^.*$;grep "FirstKeyWord" "&" | grep "SecondKeyWord";' \
| sh
打印出每个文件名,用来sed
动态地将其转换为 shell 脚本(注意转义文件名中的字符,因为这些字符用 shell 双引号括起来时可能会导致问题),然后通过 shell 运行结果。
另一个解决方案是创建一个执行处理的 shell 脚本并从 find 中调用该 shell 脚本:
$ cat grepit.sh
#!/bin/sh
grep "FirstKeyWord" "$1" | grep "SecondKeyWord"
$ find . -type f -name "*.txt" -exec sh grepit.sh {} \;
答案3
强烈不建议使用“-exec”,因为它会创建许多子进程。
请考虑将“find”与“xargs”结合使用(使用“-print0”和“-0”)
find . -type f -name "*.txt" -print0 | xargs -0 grep FirstKeyWord | grep SecondKeyWord
这样,“grep”就会为许多文件生成一次(最多可达程序可拥有的参数数量的限制)。