管道作为 find 的 -exec 参数

Flo*_*oHe 5 command-line shell pipe find

是否可以使用管道命令作为 find-exec选项的参数?这意味着,我想做这样的事情:

find . -name CMakeLists* -exec cat '{}' | grep lib \;
Run Code Online (Sandbox Code Playgroud)

我试图cat '{}' | grep lib为每个文件执行的地方,但这不起作用。引用也不起作用。有人有建议吗?

更新:

特定的问题得到了回答。现在,有没有办法让通用find <path> -type f -name <name> -exec <pipeline-command>模式起作用?

JRF*_*son 7

find . -type f -name "CMakeLists*" -exec grep lib /dev/null {} +
Run Code Online (Sandbox Code Playgroud)

此发现的文件在当前目录中基名开头或者是字符串CMakeLists。参数被转义(双引号),以便 shell 在find运行之前不会扩展它。

没有必要cat用管道添加到grep--- 这是一个无用的进程和无用的 IO,在这里。添加/dev/null确保grep在有多个文件要匹配时将报告文件名以及匹配行。

通过{} +用作-exec参数的终止序列,将多个文件名传递给grep命令的每次调用。如果我们使用,{} \;那么grep将为找到的每个文件生成一个进程。如果完成数百或数千次,不必要的流程实例化是昂贵的。

要使用带有find -exec参数的管道,您需要调用 shell。一个人为的例子可能是grep字符串“one”,但前提是字符串“two”也不存在。这可以这样做:

find . -type f -name "CMakeLists*" -exec sh -c 'grep one "$@"|grep -v two' sh {} +
Run Code Online (Sandbox Code Playgroud)

这是基于@muru、@Serg 和@Scott 的评论,在此表示感谢。

  • IIRC(虽然不确定),在 `-exec` 命令中多次使用 `{}` 可能会导致某些系统出现问题。使用`sh -c 'grep 一个"$0" | grep -v two' {} \;` 代替 (4认同)
  • 除了@muru 的评论之外,(1) 不仅不应在命令中多次使用 `{}`,而且不应将其用作命令的 *part*,如 `-exec sh -c ' grep 一 {} | grep -v two'` (1a) 因为它可能不起作用,以及 (1b) 因为它可能会引起代码注入漏洞。(2) 执行`-exec sh -c 'grep one "$1" | 可能会更好 grep -v 二' sh {} \;`。(2a) 最好有`$0`=`sh`,以防shell 发出错误消息。(2b) 这更容易扩展到`-exec sh -c 'grep one "$@" | grep -v 二' sh {} +`。 (2认同)