find exec '{}' not available after >
You could use bash -c
within the find -exec
command and use the positional parameter with the bash command:
find . \( -name '*.jpg' -o -name '*.jpeg' \) -exec bash -c 'cjpeg -quality 80 "$1" > "$(dirname "$1")/optimized_$(basename "$1")"' sh {} \;
That way {}
is provided with $1
.
The sh
before the {}
tells the inner shell its "name", the string used here is used in e.g. error messages. This is discussed more in this answer on stackoverflow.
You have an answer(https://unix.stackexchange.com/a/481687/4778), but here is why.
The redirection >
, and also pipes |
, and $
expansion, are all done by the shell before the command is executed. Therefore stdout is redirected to optimized_{}
, before find
is started.
cjpeg
has an option that lets you write to a named file, rather than standard output. If your version of find
supports the -execdir
option, you can take advantage of that to make the redirection unnecessary.
find . \( -name '*.jpg' -o -name '*.jpeg' \) \
-execdir cjpeg -quality 80 -outfile optimized_'{}' '{}' \;
Note: this actually assumes the BSD version of find
, which appears to strip the leading ./
from the file name when exanding to {}
. (Or conversely, GNU find
adds ./
to the name. There's no standard to say which behavior is "right".)