41

I have multiple images stored in a set of organized folders. I need to re-size those images to a specific percentage recursively from their parent directory. I am running Ubuntu 11.10 and i prefer learning how to do that directly from the terminal.

CompilingCyborg
  • 4,760
  • 13
  • 44
  • 61

9 Answers9

87

You could use imagemagick. For instance, for resizing all the JPG images under the current directory to 50% of their original size, you could do:

for f in `find . -name "*.jpg"`
do
    convert $f -resize 50% $f.resized.jpg
done

The resulting files will have ".jpg" twice in their names. If that is an issue, you can check the following alternatives.

For traversing/finding the files to resize, you can use xargs too. Example:

find . -name "*.jpg" | xargs convert -resize 50%

This will create copies of the images. If you just want to convert them in place, you can use:

find . -name "*.jpg" | xargs mogrify -resize 50%
betabandido
  • 18,946
  • 11
  • 62
  • 76
  • Is this a recursive process? f is a variable and $FILES is the path for the file right? – CompilingCyborg May 29 '12 at 16:04
  • 1
    The question mentions "a set of organized folders". Need a "find". – Alexander Gorshenev May 29 '12 at 16:04
  • @CompilingCyborg I changed the answer so that it handles recursion in the subfolders of the current folder, looking for all jpg images. – betabandido May 29 '12 at 16:11
  • @horsh thanks, I realize now that a way to deal with recursion was explicitly asked by the OP. I fixed by answer to include recursion. – betabandido May 29 '12 at 16:12
  • Great script. If using mogrify take care to do: mogrify -resize 50% $f and not mogrify $f -resize 50% – morpheus Mar 30 '15 at 23:56
  • The for ...; do ... done solution doesn't seem to work as is (it looks for .jpg.jpg files inside the loop). This modified version works as expected :
    for f in `find . -name "*.jpg"`; do convert `basename $f .jpg`.jpg -resize x600 `basename $f .jpg`_resized.png; done
    – Thibaud Ruelle Jun 08 '15 at 12:37
  • Sorry for the bad formatting, I wasn't able to find a way to disable the `code` markup within 5 minutes, but you get the idea ... – Thibaud Ruelle Jun 08 '15 at 12:44
  • @ThibaudRuelle Thanks for spotting that :) – betabandido Jun 09 '15 at 14:37
  • Abs great answer @betabandido but I have also handled spaces in the modified version and posted it as an alternate answer for those dealing with spaces in file names and folder names. Thanks – Gaurav Goyal Oct 29 '15 at 19:15
  • Imagemagick is a great tool for this, although it is quite resource demanding. I am currently having performance problems when trying to resize and optimize images. It can take as much as up to 15 minutes to resize a 2.4 MB size image, which is unacceptable. [See this page for more info about the approach I am using](https://www.smashingmagazine.com/2015/06/efficient-image-resizing-with-imagemagick/) – user1029978 Dec 19 '16 at 09:37
  • Is it possible to do this with images of type X11 cursor? – Aaron Franke Dec 28 '21 at 19:58
8

You can also use

sudo apt install imagemagick
sudo apt-get install nautilus-image-converter
nautilus -q

For resizing/rotating images in the current folder. You just install and then right click on an image or multiple ones and choose the size you want and that's it. The nautilus -q is to stop nautilus. Just start nautilus again, and you'll be able to use the image converter.

Nav
  • 19,885
  • 27
  • 92
  • 135
stefanbc
  • 689
  • 8
  • 10
  • Hey! This should be the accepted answer. It's so convenient to use it. Similar answer here: https://askubuntu.com/questions/1053081/how-to-install-the-right-click-photo-resizer-on-ubuntu-18-04 – Nav Jan 29 '21 at 18:08
  • I'm not sure why this is not upvoted more. I'm a programmer, so comfortable with the command line, but when I just want to resize some pictures, having a UI is way easier than looking up the imagemagick commands every time – kramer65 Jun 03 '21 at 10:31
8

Extending the answer from @betabandido

Incase there are spaces in filenames or folder names in which the images are, then one should use -print0 with find and -0 with xargs to avoid any parsing errors.

find . -name "*.jpg" -print0 | xargs -0 convert -resize 50%
find . -name "*.jpg" -print0 | xargs -0 mogrify -resize 50%
Gaurav Goyal
  • 147
  • 1
  • 4
1

It's also works if you give the new resize resolution :

convert $f.jpg -size 1024x768 $f.resized.png
Ritter
  • 11
  • 2
1

You can use imagemagick tool for batch resize.

It will maintain the aspect ratio

$ convert dragon.gif    -resize 64x64  resize_dragon.gif

It will not maintain the aspect ratio

$ convert dragon.gif    -resize 64x64\!  exact_dragon.gif

$ cat resize.sh 
#!/bin/bash
for f in `find . -name "*.jpg"`
do
    convert $f -resize 45x60\!  $f.resize.jpg
done

It will resize the image to 45x60 without maintaining the aspect ratio in current directory.

1

I modified the code of the accepted answer a little bit to include png files and add a prefix instead of a postfix to the file name to make it easier to select all resized files at once.

for p in `find . -name "*.jpg" -o -name "*.png"`
do
    d=${p%/*}
    f=${p##*/}
    b=${f%.*}
    e=${f##*.}
    convert $p -resize 33% $d/thumb.$b.$e
done

With a little modification it is possible to recreate the directory structure to a separate directory and have only resized files with the same directory structure. Another option is flattening the directory structure and having randomly generated file names and collect the path mapping to a CSV file by each thumb file with append.

inf3rno
  • 24,976
  • 11
  • 115
  • 197
0

there are a few answers like:

find . -name "*.jpg" | xargs convert -resize 50%

this won't work as it will expand the list like this: convert -resize 50% a.jpg b.jpg c.jpg which will resize a.jpg in c-0.jpg, b.jpg in c-1.jpg and let c.jpg untouched.

So you have to execute the resize command for each match, and give both input file name and output file name, with something like:

find . -name "*.jpg" | xargs -n 1 sh -c 'convert -resize 50% $0 $(echo $0 | sed 's/\.jpg/-th\.jpg/')'

each match of find is individually passed by xargs -n 1 to the resize script: sh -c 'convert -resize 50% $0 $(echo $0 | sed 's/\.jpg/-th\.jpg/')'. This script receives the file name in argument $0, uses sed to make an output file name by substitution of the original .jpg suffix by a -th.jpg one. And it runs the convert command with those two file names.

Here is the version without xargs but find -exec:

find -name '*.jpg' -exec sh -c 'convert -resize 50% $0 $(echo $0 | sed 's/\.jpg/-th\.jpg/')' {} \;
loic.jaouen
  • 489
  • 4
  • 9
  • Mmmm... with this method, you are going to have to create a new process to execute `sh` for every single JPEG, and a new process to execute `sed` for every single JPEG and a new process to execute `convert` for every single JPEG and that is going to hurt if you have lots of images. I would suggest using `mogrify` which you only invoke once and it does all your images from a single process, and/or using GNU Parallel, or, at the very least working out the new filename using shell parameter substitution rather than `sed`. – Mark Setchell Nov 12 '15 at 10:06
  • Absolutely; with `mogrify`, you don't need to work-out a second file name and all the complexity is gone. My point was that what works with `mogrify` doesn't with `convert`, as written in a couple of answers. – loic.jaouen Nov 12 '15 at 20:52
  • My point was that `mogrify` and `convert` are not simply interchangeable, as written in a couple of answers. Sure; `mogrify` does it all if you are fine with overwriting the original file. If you don't, you then want to use `convert`, and it gets a bit more messy. Get rid of sed, good idea: `find -name '*.jpg' -exec sh -c 'convert -resize 50% $0 "${0%\.jpg}-th.jpg"' {} \;` or simply by prefixing: "th-${0}" IMHO, I am not sure that the cost of creating processes matters much compared to the task of image processing... but I agree; why the hell create a new process when it is not needed? – loic.jaouen Nov 12 '15 at 21:36
0

Old question but I find which I consider the simplest method that also deals with whitespaces and non "standard" chars.

find -iname "*.jpg" -exec convert {} -resize 1280x1280 {} \;

(that's my solution with max dimension, but if you want to resize to percentage just adapt)

find -iname "*.jpg" -exec convert {} -resize 50% {} \;
Gonzalo Cao
  • 2,286
  • 1
  • 24
  • 20
0

Without XARGS and replacing the original:

After many hours struggling with my Linux ignorance (first year around), I've finally got the best solution for me:

  • using ImageMagick;
  • without XARGS;
  • replacing the original file;
  • setting a specific max for width and heigt keeping aspect ratio (700px in the following code);
  • inclusion of lettercase specific variants to avoid omissions;
  • recursively searching in all subfolders.

This is the code for the terminal:

for f in `find . -name "*.jpg" -or -name "*.JPG" -or -name "*.jpeg" -or -name "*.JPEG"` ; do convert "$f" -resize 700 "$f" ; done

I hope it helps many of you; anyways it's already saved for my future needs.

DavidTaubmann
  • 3,223
  • 2
  • 34
  • 43