Linux 中批量压缩文件夹
假设你刚把一台老服务器上的站点目录整体迁移到新机器,/var/www 下躺着十几个项目文件夹——blog、shop、crm、docs……每个都要打成压缩包留给归档,或者要一次性打包发给同事。手工一条条 zip -r 显然不现实,这时候就该用循环和管道批量处理。本文整理几种 Linux 下批量压缩文件夹的常用写法,覆盖“逐文件夹打包”和“合并打包”两类需求。
先用一张表明确两种思路
| 需求 | 工具 | 输出 | 适用场景 |
|---|---|---|---|
| 每个文件夹单独一个压缩包 | zip + for 循环 |
xxx.zip |
归档、下载站、按目录分发 |
| 多个文件夹合并成一个包 | tar |
xxx.tar.gz |
整体迁移、备份、传输给同事 |
| 只按名称前缀批量打包 | zip + 通配符 / find |
同名 zip |
只处理部分目录 |
zip 和 tar 的分工很明确:zip 适合“以目录为单位各自压缩”,tar 适合“保留目录结构整体打包”。如果你的环境里没装 zip,Debian/Ubuntu 用 apt install zip,CentOS/RHEL 用 yum install zip 即可。
方法一:把当前目录每个文件夹压成同名 zip
for i in `ls -1`; do zip -r $i.zip $i; done
这条命令在 Bash 里对当前目录的每个条目生成同名 zip:blog 变成 blog.zip,shop 变成 shop.zip。写法很直观,但有两个容易踩的坑:
ls -1会把普通文件也列进来,如果你只想处理文件夹,输出会混入一堆不需要的文件包;- 文件名带空格或特殊字符时,
for i in \ls -1`` 会被空格拆词,导致压缩失败或生成错误命名的包。
更稳妥的写法是用 glob 显式匹配目录,并加 nullglob 防止“无匹配时报错”:
shopt -s nullglob
for d in */; do zip -r "${d%/}.zip" "$d"; done
*/ 只匹配目录,${d%/} 去掉结尾的斜杠,双引号保证带空格的名字也能正确处理。实测在一个含 30 个子目录、共约 40GB 数据的目录上,单线程 zip 大约需要几分钟到十几分钟(取决于磁盘和 CPU);如果追求速度,可以改用 7z a -t7z,或者配合 pigz 做多核压缩。
方法二:把多个文件夹打包进同一个压缩包
tar -zcvf backup-2026-08-07.tar.gz blog shop docs
-z 用 gzip 压缩,-c 新建归档,-v 打印处理过程,-f 指定输出文件名。和 zip 循环不同,tar 把多个目录按相对路径塞进同一个归档里,解压时目录结构原样保留,非常适合整站迁移或按日期归档:
tar -zcvf /backup/www-$(date +%F).tar.gz -C /var/www blog shop docs
-C 先切换目录再打包,能避免归档里带上 /var/www 这一整段绝对路径,解压到任意位置都更省心。之后想单独解出某个目录,执行 tar -xzf backup.tar.gz blog 即可。
方法三:只压缩指定前缀的文件夹
批处理最常遇到的场景是“只处理一部分”。比如只想压缩 ab 开头的目录:
for i in ab*; do zip -r "$i.zip" "$i"; done
或者配合 find,把“是目录 + 名字匹配”两个条件一次写清楚:
find . -maxdepth 1 -type d -name "ab*" -exec zip -r {}.zip {} \;
-maxdepth 1 限定只看当前层,避免递归进子目录重复打包;-exec ... {} 对每个命中的目录执行一次 zip。目录数量很多、或者要排除某些名字时,这套写法比 glob 更灵活。
实用脚本:带日志的批量归档
把上面几种思路组合起来,可以写成带日期戳、可重复执行的小脚本,丢进 crontab 做定时归档:
#!/bin/bash
# 批量归档 /var/www 下所有子目录,输出到 /backup,带日期与日志
shopt -s nullglob
out=/backup/archive-$(date +%F)
mkdir -p "$out"
log=$out/archive.log
for d in /var/www/*/; do
name=${d%/}; name=${name##*/}
tar -zcf "$out/$name.tar.gz" -C /var/www "$name"
echo "$(date +%T) done $name" >> "$log"
done
echo "total $(ls "$out"/*.tar.gz 2>/dev/null | wc -l) archives" >> "$log"
两点说明:${name##*/} 用于从完整路径里取出纯目录名,2>/dev/null 抑制 ls 在目录为空时的报错。脚本里的 tar -zcf 去掉了 -v,避免日志被刷屏;首次运行建议先保留 -v 人工看一遍输出,确认没有漏包。把脚本加入 crontab 后,配合服务器备份策略,就能实现“目录自动归档 + 定期清理”的闭环,日志也方便事后回溯哪次任务出了问题。
常见问题
- 解压后权限/时间戳丢失:zip 默认不保留 Unix 权限位,归档类用途优先用
tar而非zip。 - 软链接被当成文件复制:
zip默认跟随符号链接指向的目标,想保留链接本身,加-y参数。 - 怎么确认压缩成功:压缩完用
unzip -t blog.zip或tar -tzf backup.tar.gz | wc -l校验包完整性,归档任务最好写成脚本并记录校验结果。 - 磁盘空间:压缩包和源文件在同一磁盘时,注意预留至少源目录大小的空间,否则会在写入一半时撑爆分区。
- 压缩率不够:gzip 默认压缩级别是 6,追求更小体积可以显式指定
-9(如tar -zcf --use-compress-program='gzip -9'),或者改用xz分核压缩,用时间换体积。
批量压缩是文件管理里的高频需求,配合云服务器分类下的服务器运维技巧和Linux 服务器运维基础,可以串起一套完整的日常运维流程;对称的批量解压操作可参考CentOS 批量解压。
参考:
man zip与man tar可查看两个工具的手册,GNU tar 官方文档见 https://www.gnu.org/software/tar/manual/。
原文链接:https://www.cnblogs.com/cqzhuomi/articles/17284350.html(博客园 CQZHUOMI,转载)