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.
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%
find . -name "*.jpg"
; do convert basename $f .jpg
.jpg -resize x600 basename $f .jpg
_resized.png; done</pre> –
Guck code
markup within 5 minutes, but you get the idea ... –
Guck 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.
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%
quality
works too: find . -name "*.jpg" -print0 | xargs -0 mogrify -quality 70%
–
Bailar 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% {} \;
convert
for each file separtely using -exec
. So if one image fails for any reason, others are still converted. Using xargs
runs in batch and will terminate on first error (e.g., if you have one corrupted image file then all the remaining batch is terminated). –
Monoicous It's also works if you give the new resize resolution :
convert $f.jpg -size 1024x768 $f.resized.png
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.
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.
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/')' {} \;
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
. –
Idempotent 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. –
Wirephoto 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? –
Wirephoto 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.
The script to resize all .png
files in a folder to 30%
. The original file can either be removed (if delete_original
is true), or stays, in that case the resized file would get a name postfix rename_postfix
:
#!/bin/bash
rename_postfix="-small"
delete_original=true
substr=".png"
for str in *.png; do
#reverse strings
reverse_str=$(echo $str | rev)
reverse_substr=$(echo $substr | rev)
#find index of reversed substring in reversed string
prefix=${reverse_str%%$reverse_substr*}
reverse_index=${#prefix}
#calculate last index
index=$(( ${#str} - ${#substr} - $reverse_index ))
# Extract the filename without extension
filename="${str:0:index}"
if $delete_original; then
# the name can remain, because the original will be removed
new_filename="${str}"
else
# need a new name, two files will remain
new_filename="${filename}${rename_postfix}${substr}"
fi
echo "extension = ${substr}, original = ${str}, filename = ${filename}, new = ${new_filename}"
# Resize and convert the file to .jpg
convert -resize 30% "${str}" "${new_filename}"
done
I think you should be able to write a function with the above body that would accept a directory argument, etc (if you want to make it go into subfolders)
The convert
function is from the imagemagick
library:
sudo apt install imagemagick
© 2022 - 2025 — McMap. All rights reserved.