This is a bash shell script that will optimize and compresses all JPG, JPEG, and PNG images in a local directory with the TinyPNG API. It will optimize images with these extensions: .png, .PNG, .jpg, .JPG, .jpeg, and .JPEG.
The script will not modify or delete your existing images. It will simply create an optimized copy of all the images in the directory that you specify, and it will place the optimized images in a new directory. The new directory will be named the same as the specified directory, but with the added suffix, “_tiny”. So, if you want to optimize a folder of images named “uploads”, the new folder of optimized images will be named “uploads_tiny”.
The point being that your original folder of images remains intact, with images in their original size. You’ll simply have a new folder of optimized images.
Required: you must have your TinyPNG API key.
NOTE: This script uses the TinyPNG API, and they allow a maximum of 500 images to be optimized per month, unless you have signed up with them to pay for optimizing extra images. Obviously, this script will only optimize the maximum number of images allowed per month by your TinyPNG API key.
- In the script (the script is below), on line 2, replace
YOUR_API_KEY
with your own TinyPNG API key. (Keep that key secret!) - Copy the script and use any text editor to paste the script into a new file. Save the file with the name
tinypng.sh
- Place the script in the same directory as the directory of images that you want to optimize. So, if the folder that you want to optimize with TinyPNG is called “uploads” and it’s in your “Documents” folder, then you should place the
tinypng.sh
script in the “Documents” folder.It doesn’t matter if other folders or files exist there, they’ll be ignored.
- To optimize the images, run the script. To run the script, you have to specify the name of the folder of images that you want optimized.
First, open a terminal and navigate to the directory of the script. In this example, it’s the Documents folder:
cd Documents
Run the script, specifying the name of the folder of images that you want to optimize. In this example, the folder of images is called “uploads”:
./tinypng.sh uploads
As another example, you could optimize only a sub-directory, like this:
./tinypng.sh uploads/subdir
If all goes well, you will end up with a new folder named, “uploads_tiny” (or “subdir_tiny” if you used the latter example) which contains all of the images optimized with TinyPNG. When the script is complete, it will give you a summary that tells how many files are in the original folder and how many files are in the new folder. That way, you can be sure that all the images were optimized. The end of the script also tells you the total size of both folders so you can see how much disk space you save by using TinyPNG API to optimize your images.
The Script
#!/bin/bash TINYAPIKEY="YOUR_API_KEY" # Make sure source dir is supplied if [ -z "$1" ] then echo "Missing argument. Supply the source directory containing the images to be optimized. Usage: ./tiny.sh <source_dir>" exit 1 fi INDIR=$1 # Make sure source dir exists if [ ! -d "$INDIR" ]; then echo ""$INDIR" directory not found. Supply the source directory containing the images to be optimized. Source directory should be relative to location of this script. Usage: ./tiny.sh <source_dir>" exit 1 fi DIRNAME=${INDIR##*/} OUTDIRNAME="${DIRNAME}_tiny" OUTDIR="`pwd`/$OUTDIRNAME" # Make sure output dir does not already exist with files. # If dir exists but empty, it's ok, we proceed. if find "$OUTDIRNAME" -mindepth 1 -print -quit | grep -q .; then echo "Output directory ($OUTDIRNAME) already exists. Exiting without optimizing images." exit 1 fi # Create output dir if it does not already exist if [ ! -d "$OUTDIRNAME" ]; then echo "Creating output dir "$OUTDIRNAME"..." mkdir $OUTDIRNAME fi # Begin optimizing images echo "Optimizing images..." cd $INDIR shopt -s nullglob for file in *.png *.PNG *.jpg *.JPG *.jpeg *.JPEG do Cfile=`curl https://api.tinify.com/shrink --user api:$TINYAPIKEY --data-binary @"${file}" --dump-header /dev/stdout --silent | grep Location | awk '{print $2 }'` Cfile=${Cfile// } Cfile=`echo -n "$Cfile"| sed s/.$//` curl ${Cfile} -o "${OUTDIR}/${file}" --silent done # Gather stats echo "Gathering stats..." INDIR_SIZE="$(du -h)" INDIR_FILE_COUNT="$(ls | wc -l)" cd $OUTDIR OUTDIR_SIZE="$(du -h)" OUTDIR_FILE_COUNT="$(ls | wc -l)" echo -e "Finished.rnOriginal directory ($INDIR) has $INDIR_FILE_COUNT files; total size $INDIR_SIZErnTinified directory ($OUTDIRNAME) has $OUTDIR_FILE_COUNT files; total size $OUTDIR_SIZE"
Andrew Dent
April 10th, 2017 at 6:17 pm
Hi,
Many thanks for this; it’s proven very useful on an ad-hoc basis!
I wonder – would it be possible to extend the script to allow it to:
– Recursively parse through a collection of nested sub-directories (all of which live under a parent dir)
– Within each branch, look for a particular sub-dir name (i.e. RAW)
– If found, optimise any images found within (rename original to _orig and then create a new optimised image with the orignal file name)
This is proving to be beyond my meagre skills!
Deeply appreciate any response!
Egon Lima
March 14th, 2018 at 5:33 pm
Hi,
For MAC OS environment I needed to change the hook word that you used in grep from Location to Location. Without it he can not make the cut correctly