Automatically Compress Images in Bulk Using Shell Script in Linux Environment

Publish: 2019-08-23 | Modify: 2019-08-23

In the article "Multiple Image Compression Solutions on CentOS", Xiaoz introduced the OptiPNG and jpegoptim tools for compressing images. Both of these tools support lossless compression, so Xiaoz wrote a shell script to automatically compress images in batches using OptiPNG and jpegoptim.

Supported Image Formats

Currently, the script supports .jpg/.jpeg/.bmp/.png image formats.

Implementation Principles

  1. Use the find command to search for images in the specified directory (filtering based on image size and modification time).
  2. Call different compression tools based on the image format.
  3. Use the crontab scheduled task tool to automatically compress images in batches.

Installing OptiPNG and jpegoptim

To run the shell script, it is necessary to install OptiPNG and jpegoptim. Here is an example for CentOS, but you can search and install them for other Linux systems.

# Install the epel repository
yum -y install epel-release
# Install OptiPNG
yum -y install optipng
# Install jpegoptim
yum -y install jpegoptim

Calling the Shell Script for Batch Compression

# Download the batch compression script
wget https://raw.githubusercontent.com/helloxz/shell/master/img_compress.sh
# Execute the shell script
bash img_compress.sh /data/wwwroot/imgurl

Replace /data/wwwroot/imgurl with your own image directory (use the absolute path). The execution result is as follows:

[root@imgurl ~]# bash img_compress.sh /data/wwwroot/imgurl
** Processing: /data/wwwroot/imgurl/imgs/2019/08/a259e6290bacaf3c.png
1137x557 pixels, 3x8 bits/pixel, RGB
Input IDAT size = 112086 bytes
Input file size = 112395 bytes

Trying:
  zc = 9  zm = 9  zs = 0  f = 0         IDAT size = 74656
  zc = 9  zm = 8  zs = 0  f = 0         IDAT size = 74210

Selecting parameters:
  zc = 9  zm = 8  zs = 0  f = 0         IDAT size = 74210

Output IDAT size = 74210 bytes (37876 bytes decrease)
Output file size = 74483 bytes (37912 bytes = 33.73% decrease)

/data/wwwroot/imgurl/imgs/2019/08/58427da011079d66.jpg 2228x4006 24bit N Exif IPTC JFIF  [OK] 565511 --> 565481 bytes (0.01%), optimized.
/data/wwwroot/imgurl/imgs/2019/08/bbd6e6b825079540.jpg 1440x1090 24bit N JFIF  [OK] 358749 --> 358655 bytes (0.03%), optimized.
/data/wwwroot/imgurl/imgs/2019/08/c2afa79235ce19ec.jpg 1080x1920 24bit N JFIF  [OK] 215290 --> 215290 bytes (0.00%), skipped.
/data/wwwroot/imgurl/imgs/2019/08/af0225dd07a1d19a.jpg 1080x2340 24bit N JFIF  [OK] 145853 --> 145826 bytes (0.02%), optimized.
/data/wwwroot/imgurl/imgs/2019/08/bf49aa2868dd3892.jpg 1024x1318 24bit P JFIF  [OK] 128645 --> 128548 bytes (0.08%), optimized.
/data/wwwroot/imgurl/imgs/2019/08/3d012339766e8830.jpg 9933x7017 24bit N IPTC Exif ICC XMP JFIF  [OK] 2724463 --> 2724463 bytes (0.00%), skipped.
/data/wwwroot/imgurl/imgs/2019/08/751528874c3377ef.jpg 1024x1318 24bit P JFIF  [OK] 115894 --> 115871 bytes (0.02%), optimized.
/data/wwwroot/imgurl/imgs/2019/08/c4719f67827b47b5.jpg 2208x1242 24bit N Exif IPTC JFIF  [OK] 409022 --> 136213 bytes (66.70%), optimized.
/data/wwwroot/imgurl/imgs/2019/08/97e5c418839595f8.jpg 2208x1242 24bit N Exif IPTC JFIF  [OK] 409641 --> 143095 bytes (65.07%), optimized.
/data/wwwroot/imgurl/imgs/2019/08/cd1337dbe4a9de63.jpg 2208x1242 24bit N Exif IPTC JFIF  [OK] 369246 --> 130287 bytes (64.72%), optimized.
/data/wwwroot/imgurl/imgs/2019/08/643a8733650289fc.jpg 2208x1242 24bit N Exif IPTC JFIF  [OK] 469150 --> 182604 bytes (61.08%), optimized.
/data/wwwroot/imgurl/imgs/2019/08/3fa4595aafbdcec4.jpg 2208x1242 24bit N Exif IPTC JFIF  [OK] 498075 --> 193409 bytes (61.17%), optimized.
/data/wwwroot/imgurl/imgs/2019/08/6b3a4381757675e0.jpg 776x1173 24bit N JFIF  [OK] 294311 --> 212403 bytes (27.83%), optimized.
/data/wwwroot/imgurl/imgs/2019/08/c04b62741e71b4ab.jpg 2208x1242 24bit N Exif IPTC JFIF  [OK] 502573 --> 197138 bytes (60.77%), optimized.
/data/wwwroot/imgurl/imgs/2019/08/cc3e5311aa96dcd1.jpg 2560x1440 24bit N JFIF  [OK] 787748 --> 162981 bytes (79.31%), optimized.
/data/wwwroot/imgurl/imgs/2019/08/f1c439711b64a9f1.jpg 1229x1410 24bit N JFIF  [OK] 308777 --> 136253 bytes (55.87%), optimized.
/data/wwwroot/imgurl/imgs/2019/08/74c80a3b91d20c4e.jpg 1386x1920 24bit N Exif JFIF  [OK] 241196 --> 241196 bytes (0.00%), skipped.
/data/wwwroot/imgurl/imgs/2019/08/93f17bbf3f4e00d0.jpg 1056x984 24bit N Exif JFIF  [OK] 231805 --> 115288 bytes (50.27%), optimized.

Setting up crontab for Scheduled Execution

# Assign execution permissions to the script
chmod +x img_compress.sh
# Add a scheduled task
crontab -e
# Copy the following content to the end and save (execute every hour)
*/60  * * * * /yourpath/img_compress.sh /data/wwwroot/imgurl > /dev/null
# Reload crontab
service crond reload
  • /yourpath/img_compress.sh is the absolute path to the script.
  • /data/wwwroot/imgurl is the absolute path to the images.

Comparison with tinyPNG

  • tinyPNG solution: Good compression efficiency, lossy compression, slow speed, and limited number of free uses.
  • OptiPNG and jpegoptim solution: Lossless compression, customizable compression level, compression speed depends on the level and your server configuration.

Conclusion

The script by default searches for image files modified within the past 60 minutes (and with a scheduled task running every hour, it will not compress duplicate images). Only images larger than 100kb will be compressed. You can download the script and modify these settings as needed (you can also adjust the compression level). This solution is suitable for Linux server environments where images are stored.

Additional Reading:

Script Source Code: https://github.com/helloxz/shell/blob/master/img_compress.sh


Comments