pzip 是一个并发 ZIP 压缩与解压工具,提供命令行程序 pzip、punzip,也可以作为 Go 包使用。
- 多协程支持:快速并行处理 ZIP 文件的压缩与解压
- ZIP64 支持:处理大于 4GB 的文件及超大档案
- 兼容 PKZIP 2.04g 版本:确保与传统 ZIP 工具的兼容性
- 支持原生参数:兼容 zip 和 unzip 的常用命令行参数,易于集成到现有工作流中
注意:pzip 以并发方式压缩文件,不保证 ZIP 包内 entry 的顺序与输入路径或文件系统遍历顺序一致。
下载二进制文件:
使用 Go 安装:
go install github.com/zdz1715/pzip/cmd/pzip@latest
go install github.com/zdz1715/pzip/cmd/punzip@latest从源码构建:
git clone https://github.com/zdz1715/pzip.git
cd pzip
make release-snapshot构建产物会输出到 dist/ 目录。
常用参数:
pzip:
-r, --recursive 递归压缩目录
-q, --quiet 静默模式
-x, --exclude pattern 排除匹配条目
-i, --include pattern 只包含匹配条目
-z, --comment text 写入 ZIP 注释
--strip-prefix path 去除压缩包内路径前缀
--add-prefix path 增加压缩包内路径前缀
--concurrency n 并发数
--level n 压缩级别,范围 -2 到 9
--stdlib 使用标准库 deflate
--no-dereference 将符号链接保存为链接
punzip:
-d, --dir path 解压目录
-l, --list 查看文件列表
-z, --display-comment 显示 ZIP 注释
-q, --quiet 静默模式
-x, --exclude pattern 排除匹配条目
-i, --include pattern 只解压匹配条目
--concurrency n 并发数
压缩到 ZIP 文件:
err := pzip.Compress(ctx, "archive.zip", &pzip.CompressOptions{
Sources: []string{"dir", "README.md"},
Recursive: true,
StripPrefix: "dir",
AddPrefix: "release",
Filter: pzip.NewFilter(nil, []string{"*.log"}),
Comment: "release files",
})压缩到 io.Writer:
err := pzip.CompressToWriter(ctx, w, &pzip.CompressOptions{
Sources: []string{"dir"},
Recursive: true,
})解压 ZIP:
err := pzip.Extract(ctx, "archive.zip", &pzip.ExtractOptions{
Destination: "output",
Filter: pzip.NewFilter([]string{"*.yaml"}, nil),
})读取 ZIP 注释:
comment, err := pzip.Comment("archive.zip")打开 ZIP reader:
reader, err := pzip.OpenReader("archive.zip")
if err != nil {
return err
}
defer reader.Close()
for _, f := range reader.File {
fmt.Println(f.Name)
}过滤规则匹配 ZIP entry name,路径分隔符使用 /。
示例:
*.go
dir/*
testdata/*
*.{go,md}
匹配语义兼容 Info-ZIP:* 和 ? 默认可以匹配路径分隔符 /。例如,*.go 会匹配任意目录层级中的 Go 文件。命令行中的模式需要使用引号,避免被 shell 提前展开,如 -i '*.go'。
同时设置 include 和 exclude 时,条目必须匹配 include,并且不能匹配 exclude。
以下数据来自历史测试,实际结果会受 CPU、磁盘、文件类型和并发数影响。
测试环境:
- 操作系统:Ubuntu 20.04
- CPU:Intel(R) Xeon(R) Gold 6254 CPU @ 3.10GHz(16 核)
- 内存:16GB
- 测试文件大小:23GB
使用原生zip命令:
$ time zip -r -q test-zip.zip bigdata-dir
real 14m7.312s
user 13m34.856s
sys 0m21.796s使用pzip命令:
$ time pzip -r -q test-pzip.zip bigdata-dir
real 1m30.363s
user 3m42.956s
sys 1m10.184s压缩效率大约提升了9.4倍,节省了89.6%时间。
使用原生unzip命令:
$ time unzip -q test-zip.zip
real 2m26.580s
user 2m10.276s
sys 0m14.364s使用punzip命令:
$ time punzip -q test-pzip.zip
real 0m28.078s
user 1m38.200s
sys 0m16.384s解压效率大约提升了3.22倍,节省了68.9%时间。
使用原生zip命令:
$ time zip -r -q test-zip.zip bigdata-dir
real 21m46.643s
user 18m25.877s
sys 1m56.902s使用pzip命令:
$ time pzip -r -q test-pzip.zip bigdata-dir
real 6m30.449s
user 10m17.789s
sys 11m14.409s压缩效率大约提升了3.5倍,节省了71.43%时间。
使用原生unzip命令:
$ time unzip -q test-zip.zip
real 5m55.984s
user 3m36.254s
sys 1m45.136s使用punzip命令:
$ time punzip -q test-pzip.zip
real 3m37.963s
user 4m51.073s
sys 7m9.020s解压效率大约提升了1.64倍,节省了38.8%时间。
相关 issue:
- archive/zip: zip64 extra headers problems · Issue #33116 · golang/go
- [zip] 7z complains about "Headers Error" when large files are added to a zip archive · Issue #623 · klauspost/compress
相关 issue: