You might want to use find
for this:
find . -type d -exec bash -c 'cd "$0" || exit; shopt -s nullglob; f=( *.jpg ); ((${#f[@]})) && echo convert "${f[@]}" "${PWD##*/}.pdf"' {} \;
This will recurse into each subdirectory and for each execute the Bash commands:
cd "$0" || exit
shopt -s nullglob
f=( *.jpg )
((${#f[@]})) && echo convert "${f[@]}" "${PWD##*/}.pdf"
- The
$0
will expand to the argument given to Bash, i.e., the directory found byfind
. Theexit
is here as a security in case it's impossible tocd
in there: you don't want to have random commands executed in this case. shopt -s nullglob
: if there are no matches, the globs expand to nothing. Useful if there are subdirectories with no filenames ending in.jpg
.- build an array
f
of all the filenames in current directory with a filename ending in.jpg
. This array is empty if there are no such files (thanks to thenullglob
shell option). If the array
f
is non-empty, execute the command:echo convert "${f[@]}" "${PWD##*/}.pdf"
(by the way, your
echo ${PWD##*/}.pdf
is wrong, see below).
I put an echo
in front of convert
, so that nothing is actually performed; the command is shown on standard output, for you to visually check if everything works as you expect. If this is the case, just remove the echo
!
You asked in a comment: why do you say the following line is wrong?
convert *.jpg `echo ${PWD##*/}`.pdf
you even say since it worked. To work and to be correct are not equal in computer science. The it works sentence should be understood in the full following form: it works until it fails. The most obvious case where this fails is if the directory name contains spaces: imagine a directory name of hello world
then convert will see hello
as an argument on its own, and world.pdf
as the last argument. Very likely not what you want. Besides, the following is correct (and shorter and easier to understand):
convert *.jpg "${PWD##*/}.pdf"