@StephaneChazelas 对此问答发布了以下解决方案:使用“find -exec {} +”时遇到一些问题。
$ find . -iname "*.extension" -exec sh -c '
exec <command> "$@" <additional parameters>' sh {} +
这里究竟发生了什么?最后一个具体是sh {}
做什么的呢?看起来它只是为了安抚 find 的-exec
命令,以便它有事情可做,一个 NOOP。
我可以很容易地放在echo {}
那里,它看起来工作得很好。
答案1
语法是:
find ... -exec cmd {} +
find
将根据中的条件找到许多文件,...
并cmd
使用该文件路径列表作为参数运行,尽可能多,而不超过命令参数大小的限制。
如果需要,它可能会拆分文件列表并调用cmd
多次。例如,它最终可能会调用:
cmd ./file1 ./file2 ... ./file3000
cmd ./file3001 ./file3002 ... ./file4321
这样做的一个限制是它{}
必须是最后一个。例如,你不能写:
find ... -exec cmd {} other args +
就像你可以用';'
代替'+'
.
你可以写:
find ... -exec echo foo {} +
但不是:
find ... -exec echo {} foo +
因此,如果您确实需要在文件列表后面添加一些额外的参数cmd
,则必须求助于调用 shell。 (您需要调用 shell 的其他原因是任何时候您需要使用 shell 功能,如重定向、管道、一些字符串扩展......)
在 中sh -c 'inline-script' x a b c
,对于inline-script
、$0
is x
、$1
is a
、$2
is b
..."$@"
这 3 个参数的列表也是如此:a、b 和 c。所以在:
find ... -exec sh -c 'cmd "$@" other arg' find-sh {} +
为了内联脚本,$0
(例如在显示错误消息时使用)设置为 ,find-sh
并且"$@"
是文件列表(find
扩展{}
为的内容)。
通过使用exec
shell 的特殊内置函数:
find ... -exec sh -c 'exec cmd "$@" other arg' find-sh {} +
我们告诉 shell 不要 fork 一个额外的进程来运行cmd
,而是在同一个进程中运行它(用该命令替换正在运行的 shell 进程)。一些 shellzsh
和 的一些实现ksh
会隐式地对内联脚本中的最后一个命令执行此操作(bash
当内联脚本中只有一个命令时也是如此)。