Execute a comand for each file within a directory

76 views Asked by At

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' _ {} \;

1

There are 1 answers

3
Gairfowl On BEST ANSWER

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.