如何将组合命令传递给“find -exec”?

如何将组合命令传递给“find -exec”?

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这两个替代方案:FirstKeyWordSecondKeyWordSecondKeyWordFirstKeyWord

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”就会为许多文件生成一次(最多可达程序可拥有的参数数量的限制)。

相关内容