Linux 中批量压缩文件夹

假设你刚把一台老服务器上的站点目录整体迁移到新机器,/var/www 下躺着十几个项目文件夹——blogshopcrmdocs……每个都要打成压缩包留给归档,或者要一次性打包发给同事。手工一条条 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.zipshop 变成 shop.zip。写法很直观,但有两个容易踩的坑:

  1. ls -1 会把普通文件也列进来,如果你只想处理文件夹,输出会混入一堆不需要的文件包;
  2. 文件名带空格或特殊字符时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.ziptar -tzf backup.tar.gz | wc -l 校验包完整性,归档任务最好写成脚本并记录校验结果。
  • 磁盘空间:压缩包和源文件在同一磁盘时,注意预留至少源目录大小的空间,否则会在写入一半时撑爆分区。
  • 压缩率不够:gzip 默认压缩级别是 6,追求更小体积可以显式指定 -9(如 tar -zcf --use-compress-program='gzip -9'),或者改用 xz 分核压缩,用时间换体积。

批量压缩是文件管理里的高频需求,配合云服务器分类下的服务器运维技巧Linux 服务器运维基础,可以串起一套完整的日常运维流程;对称的批量解压操作可参考CentOS 批量解压

参考:man zipman tar 可查看两个工具的手册,GNU tar 官方文档见 https://www.gnu.org/software/tar/manual/
原文链接:https://www.cnblogs.com/cqzhuomi/articles/17284350.html(博客园 CQZHUOMI,转载)