I need to convert a series of images from one format to another, but only the images within $PWD
, ignoring anything in subdirectories. But I need to remove the original extension or suffix, in order to pass it to another software down the pipeline. I'm trying to use the following command
find . -type f -iname "*.pdf" -exec convert {} $(basename {} .pdf).png \;
The intention is to keep the *.pdf
files, and have new *.png
files. However, the resulting files instead end up with the extension .pdf.png
From what I understand, the $(basename {} .pdf)
is being executed before the find
command, resulting in a literal {}
, and that's why the output of convert is {}.png
.
Should I add any particular combination of "`´'
, or maybe an explicit call to sh -c
to make this work?
I'm using zsh as my shell
Any help is appreciated
Edit: As pointed in the comments, the code and my accepted answer will process files in any possible subdirectories. To avoid this (whis is my original intention, although I don't have any subdirs)
find . -maxdepth 1 -iname "*.pdf" -exec zsh -c 'convert $1 ${1:r}.png' _ {} \;
Using find
:
find . -type f -iname "*.pdf" -exec zsh -c 'convert $1 ${1:r}.png' _ {} \;
In just the current directory, not any subdirectories:
find . -maxdepth 1 -type f -iname "*.pdf" -exec zsh -c 'convert $1 ${1:r}.png' _ {} \;
Using a shell loop. Unlike find
, this does not launch a subshell for each file:
setopt extendedglob
for fl in (#i)**/*.pdf; do
convert $fl ${fl:r}.png
done
In only the current directory:
...
for fl in (#i)*.pdf; do
...
Using a loop in an anonymous function so if fits comfortably in a single line
(directory and subdirectories / current directory only):
(){for a; convert $a $a:r.png} **/*.(pdf|PDF)
(){for a; convert $a $a:r.png} *.(pdf|PDF)
Using zmv
(recursive directory and subdirectories / current directory only):
autoload zmv # can be in ~/.zshrc
zmv -p convert '(#i)(*/)#*.pdf' '${f:r}.png'
zmv -p convert '(#i)*.pdf' '${f:r}.png'
The r
(root) expansion modifier is described in the history expansion section of the zsh
manual. Like basename
, it removes the extension from a filename.