bash - 我可以做:find .... -exec this && that?

Mar*_*tus 28 bash find

有没有办法在逻辑上组合使用find-exec调用的两个 shell 命令?

例如,打印出所有包含字符串 foo 及其出现的.csv文件,我想这样做:

find . -iname \*.csv -exec grep foo {} && echo {} \;
Run Code Online (Sandbox Code Playgroud)

但是bash抱怨“缺少'-exec'的参数”

Sté*_*las 28

-exec是一个谓词,它运行命令(不是 shell)并根据命令的结果(零或非零退出状态)评估为

所以:

find . -iname '*.csv' -exec grep foo {} \; -print
Run Code Online (Sandbox Code Playgroud)

如果在文件中找到 foo将打印文件路径grep。而不是-print您可以使用另一个-exec谓词或任何其他谓词

find . -iname '*.csv' -exec grep foo {} \; -exec echo {} \;
Run Code Online (Sandbox Code Playgroud)

另请参阅用于否定和!-o查找运算符。

或者,您可以将 shell 启动为:

find . -iname '*.csv' -exec sh -c '
   grep foo "$1" && echo "$1"' sh {} \;
Run Code Online (Sandbox Code Playgroud)

或者避免必须为每个文件启动一个 shell:

find . -iname '*.csv' -exec sh -c '
  for i do
    grep foo "$i" && echo "$i"
  done' sh {} +
Run Code Online (Sandbox Code Playgroud)


Gil*_*il' 11

您面临的问题是 shell 首先解析命令行,然后看到两个由&&运算符分隔的简单命令:find . -iname \*.csv -exec grep foo {}, 和echo {} \;。引用&&( find . -iname \*.csv -exec grep foo {} '&&' echo {} \;) 绕过了它,但现在执行的命令find类似于grep参数foo, wibble.csv, &&,echowibble.csv。您需要指示find运行将解释&&运算符的外壳程序:

find . -iname \*.csv -exec sh -c 'grep foo "$0" && echo "$0"' {} \;
Run Code Online (Sandbox Code Playgroud)

请注意,后面的第一个参数sh -c SOMECOMMAND$0,不是$1

您可以通过将命令调用与-exec … +. 为了便于处理,传递一些虚拟值,$0以便"$@"枚举文件名。

find . -iname \*.csv -exec sh -c 'for x in "$@"; do grep foo "$x" && echo "$x"; done' \ {} +
Run Code Online (Sandbox Code Playgroud)

如果 shell 命令只是由 分隔的两个程序&&,则find可以自己完成这项工作:编写两个连续的-exec动作,只有当第一个动作以状态 0 退出时才会执行第二个动作。

find . -iname \*.csv -exec grep foo {} \; -exec echo {} \;
Run Code Online (Sandbox Code Playgroud)

(我假设grepecho仅用于说明目的,因为-exec echo可以替换为-print并且结果输出无论如何都不是特别有用。)

  • 我倾向于避免使用“$0”,因为它也被 shell 用来显示错误消息。例如,您可能会看到令人困惑的“./some-file: grep: command not found”错误消息。`-exec find sh -c '... "$1"' sh {} \;` 不会有问题。您的第二个 find 命令中有一个错字(相关)。 (2认同)