重要步骤
1、解压压缩包到指定目录;
2、从解压目录中筛选出大小过大的图片移动到别的文件,大小过大的图片手动减少大小后再处理;
3、当解压目录中还有图片时,从解压后的目录中选取一定数量(比如100张)的图片移动到另外一个文件夹A;
4、压缩文件夹A,若新压缩包过大,则删除压缩包,并将文件夹A中一半图片移回原来的解压目录,重新压缩文件A并重复后续动作,直到新压缩包大小满足要求;
5、重复3、4步骤直到解压目录没有图片,操作结束。
split.sh
#!/bin/bash
#*******************************************************
# 本脚本用以将图片数量巨大的压缩包文件拆解成小的压缩包 *
# 以便以小的压缩包为单位使用 *
# 【重要】要求大的压缩包文件内没有目录结构 *
#*******************************************************
# 压缩包文件名,不带文件后缀名
zip_file_name="$1"
# 当前目录
CURRENT_DIR="$(cd `dirname $0`; pwd)"
# 解压目录
UNZIP_DIR="${CURRENT_DIR}/${zip_file_name}"
# 图片目录
PIC_DIR="${CURRENT_DIR}/pic"
# 压缩包目录,存放小压缩包
ZIP_DIR="${CURRENT_DIR}/zip"
# 大图片优化目录
OPT_DIR="${CURRENT_DIR}/optimize"
# 压缩包文件大小最大值:30M
ZIP_MAX_SIZE="$((30*1024*1024))"
# 图片文件大小最大值:2M
PIC_MAX_SIZE="$((2*1024*1024))"
# 压缩图片
function zipPic() {
img_num=$1
# 从解压目录移出100张图片到图片目录
ls "${UNZIP_DIR}" | tail -"${img_num}" | xargs -i mv "${UNZIP_DIR}"/{} "${PIC_DIR}"
# 压缩图片
zip "${ZIP_DIR}/${count}.zip" pic/*
# 校验压缩包大小
zip_size=`ls -l "${ZIP_DIR}/${count}.zip" | awk '{ print $5 }'`
half_num=${img_num}
while [ "${zip_size}" -gt "${ZIP_MAX_SIZE}" ]
do
# 删除压缩包
rm -rf "${ZIP_DIR}/${count}.zip"
# 移回图片目录下一半的图片到解压目录
half_num="$((${half_num}/2))"
ls "${PIC_DIR}" | tail -"${half_num}" | xargs -i mv "${PIC_DIR}"/{} "${UNZIP_DIR}"
# 重新压缩
zip "${ZIP_DIR}/${count}.zip" pic/*
zip_size=`ls -l "${ZIP_DIR}/${count}.zip" | awk '{ print $5 }'`
done
# 清理图片目录
rm -rf "${PIC_DIR}"/*
}
# 优化图片,无损压缩,支持jpg,需要安装jpegoptim
function optimizePic() {
find "${OPT_DIR}" -name '*.jpg' | xargs jpegoptim --strip-all
echo "$(date +%Y-%m-%d %H:%M:%S): 无损压缩图片完成。"
}
# 创建目录
function createDir() {
# 创建图片目录用以存放要压缩的图片
if [ -d "${PIC_DIR}" ];then
rm -rf "${PIC_DIR}"
fi
mkdir "${PIC_DIR}"
# 创建压缩目录用以存放小压缩包
if [ -d "${ZIP_DIR}" ];then
rm -rf "${ZIP_DIR}"
fi
mkdir "${ZIP_DIR}"
# 创建大图片优化目录用以存放单张大小超过2M的图片
if [ -d "${OPT_DIR}" ];then
rm -rf "${OPT_DIR}"
fi
mkdir "${OPT_DIR}"
echo "$(date +%Y-%m-%d %H:%M:%S): 创建目录完成。"
}
# 解压ZIP压缩包到解压目录下
function unzipTarget() {
if [ -d "${UNZIP_DIR}" ];then
rm -rf "${UNZIP_DIR}"
fi
unzip -o -d "${UNZIP_DIR}" "${zip_file_name}.zip"
echo "$(date +%Y-%m-%d %H:%M:%S): 解压目标压缩包完成。"
}
# 检查单张图片大小是否大于2M
function checkPic() {
for filename in `ls "${UNZIP_DIR}"`
do
file_size=`ls -l "${UNZIP_DIR}/${filename}" | awk '{ print $5 }'`
if [[ "${file_size}" -gt "${PIC_MAX_SIZE}" ]]; then
echo "${filename}图片大小大于2M,已移至优化目录,需要手工处理"
mv "${UNZIP_DIR}/${filename}" "${OPT_DIR}"
fi
done
echo "$(date +%Y-%m-%d %H:%M:%S): 检查图片大小完成。"
}
# 重新压缩成小的压缩包
function zipToSmall() {
file_count=`ls "${UNZIP_DIR}" -l |grep "^-"|wc -l`
count=1
img_num=100
while [ "${file_count}" -gt 0 ]
do
if [[ "${file_count}" -ge "${img_num}" ]]; then
zipPic ${img_num}
else
zipPic ${file_count}
fi
file_count=`ls "${UNZIP_DIR}" -l |grep "^-"|wc -l`
let count+=1
done
echo "$(date +%Y-%m-%d %H:%M:%S): 重新压缩成小的压缩包完成。"
}
# 清理目录
function clearDir() {
rm -rf "${UNZIP_DIR}"
rm -rf "${PIC_DIR}"
echo "$(date +%Y-%m-%d %H:%M:%S): 清理目录完成。"
}
echo "$(date +%Y-%m-%d %H:%M:%S): $0脚本执行开始..."
createDir
unzipTarget
checkPic
# 无损压缩图片
# optimizePic
zipToSmall
clearDir
echo "$(date +%Y-%m-%d %H:%M:%S): $0脚本执行结束."
例如有压缩包名为image.zip,则脚本执行命令为:sh
split.sh image
注意,使用时压缩包和脚本在同一级目录。
代码细节解析
1、解压压缩包
unzip -o -d "${UNZIP_DIR}" "${zip_file_name}.zip"
命令结构:unzip -o -d [target dir] [file name].zip
-d 指定解压目录
-o 表示解压后覆盖已存在的解压目录内容
2、从解压目录移出100张图片到图片目录
ls "${UNZIP_DIR}" | tail -"${img_num}" | xargs -i mv "${UNZIP_DIR}"/{} "${PIC_DIR}"
命令结构:ls [source dir] | tail -[file number] | xargs -i mv [source dir]/{} [target dir]
如果是脚本当前目录,则命令示例为:ls | tail -100 | xargs -i mv {} tmp/
其中[source dir]因为是当前目录则可以省略。
3、压缩图片
zip "${ZIP_DIR}/${count}.zip" pic/*
命令结构:zip [location]/[name].zip [target dir]
zip命令后面跟了两个参数,第一个是新压缩包的存储位置和压缩包名称,第二个是压缩目录位置。
第二个参数还决定了压缩后压缩包内目录结构,当[target dir]是形如"/image/pic"或"image/pic"时,压缩包内结构目录将与之一致,将有两级目录。
若不需要目录结构,增加-j参数即可,则命令可以是:zip -j [location]/[name].zip [target dir]
4、获取压缩包大小
zip_size=`ls -l "${ZIP_DIR}/${count}.zip" | awk '{ print $5 }'`
命令结构:ls -l [file name] | awk ‘{print $5}’
命令的意思是,列出文件详细信息,通过awk命令获取第5个参数值。例如:
从左往右数,第五个是“101919574”,即文件大小值,单位 bit
5、打印日志
echo "$(date +%Y-%m-%d %H:%M:%S): $0脚本执行开始..."
时间格式:年-月-日 时:分:秒
$0 获取的是当前脚本名称
6、获取目录下文件数量
file_count=`ls "${UNZIP_DIR}" -l |grep "^-"|wc -l`
命令结构:ls [target dir] -l | grep “^-” | wc -l
7、无损压缩工具安装
在linux环境依次执行以下命令:
1)yum install optipng -y
2)yum install -y libjpeg libjpeg-devel
3)wget
http://freecode.com/urls/fbbba65c1ddc8766cf74c3db8d2547a8
该步骤可能下载下来文件名称就叫fbbba65c1ddc8766cf74c3db8d2547a8,则在windows系统浏览器访问 “
http://freecode.com/urls/fbbba65c1ddc8766cf74c3db8d2547a8” 会自动下载文件“jpegoptim-1.4.1.tar.gz”,上传到linux环境就好。
4)tar -xvzf jpegoptim-1.4.1.tar.gz
5)cd jpegoptim-1.4.1/
6)./configure
7)make && make install
8、无损压缩
find "${OPT_DIR}" -name '*.jpg' | xargs jpegoptim --strip-all
命令结构:find [target dir] -name [target picture] | xargs jpegoptim --strip-all
命令的意思是,根据名称搜索对应图片并用jpegoptim工具无损压缩。
find [target dir] -name [target file]是常用的查找工具命令格式,如果是当目录则可以是:find . -name *.jpg 其中“.”表示当前目录,“*.jpg”是满足后缀为“.jpg”的所有文件。find命令是根据名称模糊条件进行搜索。
因为该工具是无损压缩,压缩比例不大,例如2.8M的图片压缩后是2.5M左右。