Generate and move thumbnails recursively
Don't iterate over the output of find
.
The problem you are experiencing is a typical consequence of that.
Your example is a bit tricky due to the file renaming.
One not very efficient but safe way to do it is with the -exec
option of find
, and an additional sh
per each file, like this:
find . -type f -iname "*.jpg" -exec sh -c 'echo convert "$1" -resize 800x800\> /home/user/thumbs/"${1%.jpg}_thumb.jpg"' -- {} \;
If you didn't mind using the same name (with .jpg
suffix instead of _thumb.jpg
), then this simple form would work, and be much more efficient:
find . -type f -iname "*.jpg" -exec echo convert "{}" -resize 800x800\> /home/user/thumbs/"{}" \;
I added echo
statements there to check the output before executing the commands. Remove them if the output looks good.
You could use more advanced options like -set
combined with percent escapes (namely %t
to extract the filename without directory or extension) to do the resize, rename and move of each file with a single convert
invocation:
find . -type f -iname \*.jpg -exec convert {} -resize 800x800\> \
-set filename:name '%t' '/home/user/thumbs/%[filename:name]_thumb.jpg' \;
In your solution the file names got split on the default $IFS
which includes spaces.
Try the following:
while IFS= read -rd '' f; do
convert ./"$f" -resize 800x800\> ./"${f%.jpg}_thumb.jpg"
mv ./"${f%.jpg}_thumb.jpg" /home/user/thumbs/
done < <(find . -type f -iname "*.jpg" -print0)
The find
prints the file names separated by null bytes (\0
) and using -d ''
you set the delimiter of read
to the same.