Large images means a large page size which means slow WordPress page load times for users. The most common culprit is image size or lack of compression. If you never had any image size restrictions or automatic resizing on your site, it can be extremely convenient to batch resize those images in Linux.
This guide shows you how to batch resize jpg and png files using Imagemagick on Ubuntu or Debian. If you want to install Imagemagick on CentOS see this guide.
Batch Resize Images using Linux Command Line and Imagemagick
First we need to install Imagemagick from the repository on Debian or Ubuntu
sudo apt-get update
sudo apt-get install imagemagick -y
We can use the identify
command to get the width (%w
) and height (%h
)
identify -format "%wx%h" image.jpg
You will see the resolution, width is first then height.
3960x2120
You can resize the image if it is larger than the specified dimensions. This will automatically preserve the aspect ratio of the image too.
Note that this overwrites your original image!
convert image.jpg -resize 600x400\> image.jpg
Check the image was resized
identify -format "%wx%h" image.jpg
All good!
600x321
Now we can move on to batch resizing
Batch Resize Images with Linux with Imagemagick
Create the following script
mkdir -p ~/scripts
nano ~/scripts/batch-image-resize.sh
Paste the script below, remember to change the FOLDER
variable!
FOLDER
is the absolute path to your image folder
WIDTH
is the max width and HEIGHT
is the max height.
It will overwrite your original images so make sure you have a backup before running this!
#!/usr/bin/env bash
# Purpose: batch image resizer
# Source: https://guides.wp-bullet.com
# Author: Mike
# absolute path to image folder
FOLDER="/var/www/wp-bullet.com/wp-content/uploads"
# max width
WIDTH=540
# max height
HEIGHT=300
#resize png or jpg to either height or width, keeps proportions using imagemagick
#find ${FOLDER} -iname '*.jpg' -o -iname '*.png' -exec convert \{} -verbose -resize $WIDTHx$HEIGHT\> \{} \;
#resize png to either height or width, keeps proportions using imagemagick
#find ${FOLDER} -iname '*.png' -exec convert \{} -verbose -resize $WIDTHx$HEIGHT\> \{} \;
#resize jpg only to either height or width, keeps proportions using imagemagick
find ${FOLDER} -iname '*.jpg' -exec convert \{} -verbose -resize $WIDTHx$HEIGHT\> \{} \;
# alternative
#mogrify -path ${FOLDER} -resize ${WIDTH}x${HEIGHT}% *.png -verbose
Ctrl+X, Y and Enter to save and exit.
Check the folder size
du -sh foldername
Check output size
220MB
Screen will ensure the batch command keeps on running even if your SSH session is terminated.
sudo apt-get install screen
Create a new screen session, press space or enter at the intro screen
screen
Execute the script
bash ~/scripts/batch-image-resize.sh
Detach the screen with Ctrl+A and pressing D (detach).
You can use the top command and look for jpegoptim processes once in a while.
Reattach the screen like so
screen -r
Check the folder size again
du -sh foldername
You should see an improvement
186MB
Make sure to compress your images with lossless (guide) or lossy compression (guide).
If you need to do some more advanced find commands that use regex this should help.
Sources
Using find to Search for Multiple Extensions
How to get Image Information with Linux
Imagemagick Shrink
Resize Images and Keep Ratio
thanks for this interesting approach…cannot see any activity when running the script…just a quick cessation/no-result…the isolated “convert” command does work for me…is there a way to step through a bash script?…when i run the script without customizing the folder-name it does execute and reports the expected error (find: `/var/www/wp-bullet.com/wp-content/uploads’: No such file or directory)
You are welcome, you need to change the find path to your own by replacing /var/www/wp-bullet.com/ with your own path.
Thanks for the reply. I did subsequently replace with the desired path, but when the script is run it merely fails silently. I do not know what to do next. thanks again
Could be there are no images there, what output do you get from find $FOLDER -iname ‘*.jpg’ -o -iname ‘*.png’ because if that returns no results then there are no images for the script to resize.
fyi the jpg are 15.9 megapixels, the files are each about 6-8 MB
Please check the updated script which adds verbosity so you can see the images are being resized 🙂
Can’t see any activity either. Convert works on an individual file. The test folder is correctly identified and there’s a 4000 wide image in it. Width limit set to 1024 and height set to 10000 just to keep it out of the way. I just get an instant cursor back. Nothing happens in the directory.
Hey Craig, did you adjust the FOLDER= parameter to be your correct path? Does your FOLDER have spaces in it by any chance?
Yes, and if I shorten the last line to ….
find $FOLDER -iname ‘*.jpg’ -o -iname ‘*.png’;
It puts out a list of the files. Also tried removing the HEIGHT as ImageMagick says if only WIDTH is provided then everything stays in the same ratio but that didn’t work either.
I am actually testing this now and it seems to be working, it’s just very fast! Can you try running the identify command on some of the images in the folder you wanted to convert? I’m working on getting verbose output so it doesn’t appear to fail
-verbose in the original line makes no difference.
Using the new line (changing .png for .jpg) I get….
mogrify: unable to open image `*.jpg’: No such file or directory @ error/blob.c/OpenBlob/2712.
Yet find $FOLDER -iname ‘*.jpg’ -o -iname ‘*.png’; gives a full list of images.
Weird, I just tested with a png and jpg in the same absolute path on Linux and I get this output
root@guides:/tmp/images# bash test
/tmp/wp-cli-delete-unused-plugins.png PNG 360×111=>80×25 80×25+0+0 8-bit sRGB 1.39KB 0.000u 0:00.009
/tmp/images/wp-cli-delete-unused-plugins.png PNG 300×139=>80×37 80×37+0+0 8-bit sRGB 1.66KB 0.000u 0:00.009
Script
#!/usr/bin/env bash
# Purpose: batch image resizer Source: https://guides.wp-bullet.com
# Author: Mike absolute path to image folder
set -o errexit
set -o pipefail
FOLDER=”/tmp”
# max height
WIDTH=120
# max width
HEIGHT=80
#resize to either height or width, keeps proportions using imagemagick
find ${FOLDER} -iname ‘*.jpg’ -o -iname ‘*.png’ -exec convert {} -verbose -resize $WIDTHx$HEIGHT> {} ;
I have added verbosity to the script now so you can see the changes being made Craig, hopefully this helps!
Final line is…..
find $FOLDER -iname ‘*.jpg’ -o -iname ‘*.png’ -exec convert {} -resize $WIDTH> {} ;
WIDTH is set to 1024 and the target folder has a jpg in it that’s over 4000 wide.
I’m using Linux Mint 18.2 Cinnamon 64 bit. All up to date.
Thanks for the update Craig 🙂
Hi. Today I found your script, but after starting it, I just get the cursor back … nothing happens. The convert command for a single image is working fine.
Hi Janko, please see the comments below and let me know how that goes. If you are still struggling please consider sharing SSH access and getting in touch with me via m contact form 🙂
I already had a look. And I think I use the latest version with -verbose, but there is still no output. Maybe we could have a look together via TeamViewer?
Hey, this is excellent, is there any way to check the file size before converting, I want only image greater than 1 mb to be converted. Thanks
What a wonderful method. Easy and quick. Thanks a lot.
Your comment says height but the variable says WIDTH, and vice-versa. Helpful otherwise.
Glad to hear that Joe, sorry for the oversight 🙂
Good catch! Fixed 🙂