@StephaneChazelas posted the following solution to this Q&A: Having some trouble using “find -exec {} +”.
$ find . -iname "*.extension" -exec sh -c '
exec <command> "$@" <additional parameters>' sh {} +
What exactly is going on here? Specifically what does the last sh {}
do? It seems as though it's just there to pacify find's -exec
command so that it has something to do, a NOOP.
I could just as easily put echo {}
there and it appears to work just fine.
Best Answer
The syntax is:
find
will find a number of files based on the criteria in...
and runcmd
with that list of file paths as arguments, as many as possible without surpassing the limit on the size of the arguments to a command.If needed it may split the list of files and call
cmd
several times. For instance, it may end up calling:A limitation with that is that
{}
has to be last. You can't for instance write:like you could with
';'
instead of'+'
.You can write:
but not:
So, if you do need to add some extra arguments to
cmd
after the list of files, you have to resort to calling a shell. (Other reasons why you'd need to call a shell would be any time you need to use a shell feature like redirections, pipes, some string expansions....)In
sh -c 'inline-script' x a b c
, for theinline-script
,$0
isx
,$1
isa
,$2
isb
... so"$@"
is the list of those 3 arguments: a, b and c. So in:For the inline script,
$0
(which is used for instance when displaying error messages) is set tofind-sh
and"$@"
is the list of files (whatfind
expands{}
to).By using the
exec
special builtin of the shell:We tell the shell not to fork an extra process to run
cmd
, but instead to run it in the same process (replacing the running shell process with that command). Some shells likebash
,zsh
and some implementations ofksh
do that implicitly for the last command in a script.