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