-exec command ;
The string `{}' is replaced by the current file name being processed.
Consider the following:
% find . -type f
./file1
./file2
./file3
./file4
./file5
% find . -type f -exec sh -c 'printf "arg -> %s\n" "$0"' {} \;
arg -> ./file1
arg -> ./file2
arg -> ./file3
arg -> ./file4
arg -> ./file5
But here we execute sh -c ...
for every single file found.
Note also that the filename is passed to the shell as $0 (not $1).
If we wnat to optimize the code, as long as our command accepts more than one argument at a time for processing, we could use something like this:
% find . -type f -exec sh -c 'printf "arg -> %s\n" "$@"' {} +
arg -> ./file2
arg -> ./file3
arg -> ./file4
arg -> ./file5
Note the {} + syntax (vs. {} \;). From find man pages:
-exec command {} +
This variant of the -exec action runs the specified command on the selected files, but the command line
is built by appending each selected file name at the end; the total number of invocations of the com-
mand will be much less than the number of matched files. The command line is built in much the same
way that xargs builds its command lines.
But as you observe, the first file is missing (because $@ contains all parameters except $0). That's why we need to set our $0 by hand, in order to process all arguments correctly:
% find . -type f -exec sh -c 'printf "arg -> %s\n" "$@"' put_whatever_you_want_here {} +
arg -> ./file1
arg -> ./file2
arg -> ./file3
arg -> ./file4
arg -> ./file5
In some situations you may need to set $0 to something meaningful.