有没有办法在逻辑上组合使用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, &&,echo和wibble.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)
(我假设grep和echo仅用于说明目的,因为-exec echo可以替换为-print并且结果输出无论如何都不是特别有用。)