日常开发、数据导出、批量下载经常遇到一堆独立
.zip文件,需要把它们合成一个压缩包。这里区分两种场景:
- 把多个独立 zip 作为内部文件打包进新 zip:新 zip 里面包含若干个 zip 子文件
- 把各个 zip 内部的文件全部提取出来,合并到同一个新 zip(业务最常用)
⚠️注意:本文处理多个独立普通 zip,不是
.zip.001/.z01这种分卷压缩包,分卷是另外一套逻辑。
场景一:直接把多个 zip 文件打包进新 zip
简单理解:新 zip 里面存放的是原来的.zip文件本身,不解开内部内容。
Windows 图形界面
- 选中所有需要合并的
a.zip、b.zip、c.zip - 右键 → 发送到 → 压缩 (zipped) 文件夹
- 直接生成新 zip,内部就是原来那几个 zip 文件。
缺点:Windows 自带 zip 不支持密码、不支持高级压缩;追求功能推荐 7‑Zip(免费开源)。
Linux /macOS 命令行
bash
# 将a.zip b.zip c.zip打包为all_in_one.zip,内部保留原zip文件
zip all_in_one.zip a.zip b.zip c.zip
Python 实现
python
运行
import zipfile
zip_list = ["a.zip", "b.zip", "c.zip"]
out_zip = "all_in_one.zip"
with zipfile.ZipFile(out_zip, "w", zipfile.ZIP_DEFLATED) as zf:
for fp in zip_list:
zf.write(fp) # 直接把zip文件作为条目写入
print(f"生成完成:{out_zip}")
场景二:合并各个 zip 内部的文件(最常用)
需求:有part1.zip、part2.zip,每个 zip 里面有一堆文档图片,希望输出一个新 zip,里面是所有解压出来的文件,不再包含子 zip 包。
传统笨办法:全部解压到临时文件夹,再重新压缩。缺点:占用大量磁盘临时空间,大文件很慢。下面提供命令行、Python 两种方案。
方案 A:7‑Zip 命令行(Windows 推荐)
需要先安装 7‑Zip,把7z.exe加到环境变量或者写全路径。
思路:管道流式处理,不落地大量临时文件,读取每个 zip 内部条目,直接写入新归档。
cmd
:: Windows cmd示例,把part1.zip part2.zip内全部文件合并输出merged.zip
(for %%z in (part1.zip part2.zip) do 7z x -so "%%z") | 7z a -si merged.zip
提示:PowerShell 语法略有区别,适合写 bat 脚本批量自动化。
方案 B:Linux/macOS Shell
bash
# 方式1:临时目录中转,简单稳妥
mkdir tmp
for z in part1.zip part2.zip; do unzip -q "$z" -d tmp; done
zip -r merged.zip tmp/*
rm -rf tmp
方案 C:Python 脚本(跨平台,开发自动化首选)
不解压到磁盘,内存读取每个 zip 内部条目,写入新 zip,保留目录结构,适合程序批量处理。
python
运行
import zipfile
from pathlib import Path
def merge_inner_files(output_zip: str, input_zip_paths: list[str]):
"""
将多个zip内部的所有文件合并到同一个输出zip
:param output_zip: 输出zip路径
:param input_zip_paths: 待合并zip文件列表
"""
with zipfile.ZipFile(output_zip, "w", zipfile.ZIP_DEFLATED) as out_zf:
for zip_path in input_zip_paths:
with zipfile.ZipFile(zip_path, "r") as in_zf:
for info in in_zf.infolist():
# 跳过目录条目,只处理文件
if info.is_dir():
continue
# 读取源zip内部文件字节流,直接写入目标zip
with in_zf.open(info) as f:
out_zf.writestr(info, f.read())
print(f"✅合并完成,输出文件:{output_zip}")
if __name__ == "__main__":
files = ["part1.zip", "part2.zip", "part3.zip"]
merge_inner_files("merged_all.zip", files)
注意:如果多个 zip 内部存在同名文件,后面的会覆盖前面的,业务使用时建议增加重名冲突检测逻辑。
容易踩坑:分卷 zip 与普通 zip 不要搞混
很多人混淆两个概念:
- 多个独立 zip 文件:
a.zip、b.zip,各自独立,上面的方法处理。 - zip 分卷文件:
data.zip.001、data.zip.002,是同一个大文件拆分出来的碎片,不是独立压缩包。
分卷合并命令(Linux):
bash
cat data.zip.* > full_data.zip
Windows cmd:
cmd
copy /B data.zip.001 + data.zip.002 full_data.zip
分卷直接用 7‑Zip 打开第一个分卷文件解压即可,软件会自动识别全部片段,不需要手动二进制拼接。
各方案优缺点对比
表格
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| Windows 右键发送到压缩包 | 零安装,操作简单 | 无密码、压缩率一般 | 少量文件快速打包 |
| 7‑Zip 命令行 | 流式处理,少占磁盘,支持加密 | 需要安装 7‑Zip | Windows 批量脚本、大压缩包 |
| Shell 脚本 (unzip+zip) | Linux/macOS 原生,简单直观 | 会产生临时目录 | 服务器、CI 脚本 |
| Python zipfile | 跨平台,可嵌入业务代码,精细控制逻辑 | 需要处理重名覆盖问题 | 后端程序、自动化流水线 |
常见问题 FAQ
Q:合并后 zip 打开报错损坏?
- 区分你是要 “打包 zip 本身” 还是 “合并 zip 内部文件”,两种逻辑代码不能混用。
- Python 版本注意:加密的 zip,标准库
zipfile不支持读取加密 zip 内部内容,遇到带密码压缩包,建议改用 7‑zip 命令行。
Q:文件特别大,内存 OOM 怎么办?
上面 Python 示例一次性f.read()把文件读进内存;超大文件建议改用分块流式读写,或者退回到 “解压临时目录再压缩” 方案。
Q:保留原始目录结构吗?
示例代码会保留 zip 内部原有的目录路径;如果想要全部摊平到根目录,修改writestr第二个参数,重写 arcname。