shell 案例

批量压缩图片大小

场景

因为之前在文章中引用了很多手机拍摄图片,没注意图片体积,自己浏览时发现加载特别慢。所以想着再优化一下,我记得最开始写过类似脚本,但是找不到了,这次刚好记录一下。在AI帮助下,脚本在多次迭代优化后,已经比较稳定实用。

主要原是通过ImageMagick、jpegoptim和optipng工具,将图片压缩至指定大小,支持JPG/PNG格式,并采用多线程并行处理提升效率。

脚本分享

以下脚本支持将JPG/PNG图片压缩至指定大小(例如 100KB 以下),并自动跳过已经达标的文件。。只需要在需要处理的目录下运行脚本即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#!/bin/bash

# ===================== 核心配置 =====================
TARGET_SIZE_KB=100 # 目标大小:100KB
TARGET_SIZE=$((TARGET_SIZE_KB * 1024))
MAX_RESOLUTION=1000 # 网页合适分辨率
JPG_QUALITY=60 # JPG压缩质量
THREADS=20 # 24核用20线程
# ====================================================

# 检查依赖工具
check_dependency() {
local cmd=$1
local name=$2
if ! command -v $cmd &> /dev/null; then
echo "❌ 缺少必要工具:$name,请先安装!"
echo "Ubuntu/Debian: sudo apt install jpegoptim optipng imagemagick -y"
echo "macOS: brew install jpegoptim optipng imagemagick"
exit 1
fi
}

# 检查关键依赖
check_dependency "convert" "ImageMagick"
check_dependency "jpegoptim" "jpegoptim"
check_dependency "optipng" "optipng"

# 获取当前目录
CURRENT_DIR=$(pwd)
echo "========================================"
echo "当前目录:$CURRENT_DIR"
echo "目标:压缩至${TARGET_SIZE_KB}KB以下(${THREADS}线程)"
echo "========================================"

process_image() {
local img=$1
local TARGET_SIZE=$2
local MAX_RESOLUTION=$3
local JPG_QUALITY=$4
local filename=$(basename "$img")

# 工具函数:获取文件大小KB(兼容Linux和macOS)
get_file_size_kb() {
if [[ $(uname) == "Darwin" ]]; then
echo "scale=2; $(stat -f%z "$1")/1024" | bc
else
echo "scale=2; $(stat -c%s "$1")/1024" | bc
fi
}

# 工具函数:检查是否达标
is_size_ok() {
[[ $(stat -c%s "$1") -le $2 ]]
}

# 已达标则跳过
if is_size_ok "$img" "$TARGET_SIZE"; then
echo "⏩ $filename - 已达标($(get_file_size_kb "$img")KB),跳过"
return 0
fi

# 区分JPG/PNG处理
if [[ $img =~ \.(jpg|jpeg)$ ]]; then
echo "🔍 处理JPG:$filename(原大小:$(get_file_size_kb "$img")KB)"
# JPG压缩逻辑
convert "$img" -resize "${MAX_RESOLUTION}x${MAX_RESOLUTION}>" -strip "$img"
jpegoptim --max=$JPG_QUALITY --strip-all --overwrite "$img"

# 兜底检查
if ! is_size_ok "$img" "$TARGET_SIZE"; then
jpegoptim --max=40 --strip-all --overwrite "$img"
fi
echo "✅ $filename - 压缩后:$(get_file_size_kb "$img")KB"

elif [[ $img =~ \.png$ ]]; then
echo "🔍 处理PNG:$filename(原大小:$(get_file_size_kb "$img")KB)"
# PNG压缩逻辑
convert "$img" -resize "${MAX_RESOLUTION}x${MAX_RESOLUTION}>" -strip "$img"
optipng -o6 -strip all -force "$img"

# 兜底检查
if ! is_size_ok "$img" "$TARGET_SIZE"; then
optipng -o9 -strip all -force "$img"
fi
echo "✅ $filename - 压缩后:$(get_file_size_kb "$img")KB"
fi
}

# 导出函数(确保子shell可见)
export -f process_image

# ===================== 多线程执行 =====================
echo -e "\n[开始多线程处理所有图片(${THREADS}线程)]"

find "$CURRENT_DIR" -maxdepth 1 -type f \( -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.png" \) -print0 | \
xargs -0 -I {} -P $THREADS bash -c 'process_image "$1" "$2" "$3" "$4"' _ {} $TARGET_SIZE $MAX_RESOLUTION $JPG_QUALITY

echo -e "\n========================================"
echo "处理完成!"
echo "========================================"



参数说明

脚本开头的配置项可以根据实际需求调整:

参数 说明 推荐值
TARGET_SIZE_KB 目标图片大小 100
MAX_RESOLUTION 最大分辨率限制 1000
JPG_QUALITY JPG压缩质量 60
THREADS 并行线程数 CPU核心数 × 0.8

我电脑是24核CPU,使用20线程较为合适。

注意事项

1、脚本会直接覆盖原始图片,建议首次使用前先备份图片目录。
2、图片体积变小,图片质量就会下降,还是权衡后选择是否优化。