Sujet : Re: Executing Shell Pipelines with “find -exec”
De : usenetf24.effweh (at) *nospam* erine.email (Friedhelm Waitzmann)
Groupes : comp.unix.shell comp.os.linux.miscSuivi-à : comp.unix.shellDate : 05. May 2024, 02:49:12
Autres entêtes
Organisation : A noiseless patient Spider
Message-ID : <8l1jgk-p2u.ln1@foechtelwenk.news.arcor.de>
References : 1
Lawrence D'Oliveiro <
ldo@nz.invalid>:
However, you can explicitly invoke a shell and give it a one-shot
command with “sh -c”. While the command string must be a single word,
it is possible to have multiple argument words following this command.
So if the command happens to be “eval”, that gives you your ability to
feed the separate words of the -exec command to the shell, thus:
find . -name \*.blend -exec sh -c 'eval "${@}"' \
sh test \$\( blendfile_version {} \| jq -r .version \) -gt 304 \; -print
This works
No, it does not: What happens if find comes upon a file
“Adam & Eve.blend” or “;rm -rf -- "$HOME";.blend”? Yes, the
latter is a valid filename too! If you fill a filename into a
command string without recoding the filename to a notation of a
literal string, you can trick the command string to do things
that you did not have in mind.
I would rather put it this way:
find . -name \*.blend -exec sh -c \
'test "$( blendfile_version "$1" | jq -r .version )" -gt 304' \
sh {} \; -print
Here, find will replace the “{}” with the filename encountered
and give it as a positional parameter to the shell. Therefore it
must not and need not be quoted.
GNU find will perform this substitution even if the sequence
occurs as part of a word. This allows the -exec command to be
simplified somewhat, by getting rid of the “eval” stage:
find . -name \*.blend -exec \
sh -c '[ $(blendfile_version {} | jq -r .version ) \> 304 ]' \; \
-print
Again, this does not work with these two mindfully chosen
filenames.
The solution: Let find give the name that it comes upon as
a positional parameter to the shell:
find … -exec sh -c … sh {} \;
Please pay attention to Followup-To.