7

I have 300k+ jpg files in the same directory. Files are like:

/covers    
0788862281217.jpg
0788863155104.jpg
7888311516341.jpg
7888370920479.jpg
7888497074277.jpg

I need to batch resize saving the resized images in the same directory with a prefix th_ in filename like

th_0788862281217.jpg
th_0788863155104.jpg
th_7888311516341.jpg
th_7888370920479.jpg
th_7888497074277.jpg

all inside /covers

The following works but it overwrites the source files

$ find thumbs -type f -name "*.jpg" | xargs mogrify -resize 75x75

so I have to copy all the images into a new dir (/covers/thumbs) and then run the batch and then move all the files back to /covers

1 Answer 1

14

From the manual:

Mogrify overwrites the original image file, whereas, convert(1) writes to a different image file.

You can do:

find ./covers -type f -name '*.jpg' -execdir convert {} -resize 75x75 th_{} \;

This will probably be the most efficient if you have a large number of files.

In general, for various reasons it is a rather bad idea to pipe the output of find to xargs, unless you use the following pattern, which the GNU and BSD find variants support: find … -print0 | xargs -0 …


If you want to use shell-only commands, you can loop over the files like so:

for image in ./covers/*.jpg; do convert "$image" -resize 75x75 "$(dirname $image)/th_$(basename $image)"; done

That's the easiest (and safest) you can get, without having to resort to external commands. You will, however need to split up path and filename and insert the prefix in between. If you're already in the same folder, this is much easier:

for i in *.jpg; do convert "$i" -resize 75x75 "th_$i"; done

A universal and shorter solution with Zsh:

for i (./covers/*.jpg) convert "$i" -resize 75x75 "${i:h}/th_${i:t}"    
6
  • hi there! My files are NOT in the /thumbs folder but in /covers. So I assume the command line will become: for image in covers/*.jpg; do convert "$image" -resize 75x75 "th_$(basename $image)"; done Will this save in the same dir as the master files? Correct? Tnx!
    – Gabriele
    Commented May 19, 2013 at 19:31
  • I tried with a sample dir/files. It didn't work
    – Gabriele
    Commented May 19, 2013 at 19:37
  • Sorry, wrong folder there. See my latest update. If you want the command to work with any arbitrary folder, then you need to split up the path between dirname and basename and insert the prefix there. The following would be easier, if you're already in the folder: for i in *.jpg; do convert "$i" -resize 75x75 "th_$i"; done.
    – slhck
    Commented May 19, 2013 at 19:39
  • test with 3 images was succesful. I'll run it in the main dir with 300K+ files and I'll get back here. Thanks slhck!
    – Gabriele
    Commented May 19, 2013 at 19:43
  • 1
    If your argument list ends up too long (because of 300K+ files), try the variant using find with execdir which I added to my answer above.
    – slhck
    Commented May 19, 2013 at 19:53

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .