Automatically Batch Compress Images on Linux Using Shell Scripts
In the article Multiple Image Compression Solutions on CentOS, xiaoz introduced OptiPNG and jpegoptim tools for image compression. Both tools support lossless compression, so xiaoz wrote a Shell script to call these tools to automatically complete batch image compression.

Supported Image Formats
Currently supports .jpg, .jpeg, .bmp, and .png image formats.
Implementation Principles
- Use the
findcommand to locate images in a specified directory (with filtering by image size and time). - Call different compression tools based on the image format.
- Automate batch compression using the crontab scheduling tool.
Install OptiPNG and jpegoptim
The Shell script requires OptiPNG and jpegoptim. Installing these tools is mandatory. Here is an example for CentOS; other Linux systems can search for installation methods accordingly.
# Install EPEL repository
yum -y install epel-release
# Install OptiPNG
yum -y install optipng
# Install jpegoptim
yum -y install jpegoptim
Call 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 (must use an absolute path). The execution effect 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/af0225dd07a1d19d.jpg 1080x2340 24bit N JFIF [OK] 145853 --> 145826 bytes (0.02%), optimized.
/data/wwwroot/imgurl/imgs/2019/08/bf49aa2868dd392.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.
Crontab Scheduled Execution
# Grant execution permissions to the script
chmod +x img_compress.sh
# Add a scheduled task
crontab -e
# Copy the content to the end and save (executes once every hour)
*/60 * * * * /yourpath/img_compress.sh /data/wwwroot/imgurl > /dev/null
# Reload crontab
service crond reload
/yourpath/img_compress.shis the absolute path of the script./data/wwwroot/imgurlis the absolute path of the image directory.
Comparison with TinyPNG
- TinyPNG Solution: Good compression efficiency, lossy compression, slower speed, and limited free usage.
- OptiPNG and jpegoptim Solution: Lossless compression, customizable compression levels, and compression speed depends on the compression level and server configuration.
Conclusion
The script defaults to finding image files modified within the last 60 minutes (combined with the 1-hour crontab execution, this avoids compressing duplicate images). Only images larger than 100KB will be compressed. You can download the script and modify these settings as needed (compression levels can also be adjusted). This solution is suitable for images stored in a Linux server environment.
Extended Reading:
- ImgURL Pro Professional Edition Released, Supports Multiple External Storage, 40% Off Promotion
- CentOS Uses Mozilla JPEG to Compress Images
- Multiple Image Compression Solutions on CentOS
- Use TinyPNG to Optimize Your Website Images
Script Source Code: https://github.com/helloxz/shell/blob/master/img_compress.sh