zip默认不递归压缩子目录,需加-r参数;中文名乱码因CP437编码,新版本用-U-N=UTF8解决;排除文件用-x配合shell glob;压缩率低且无多线程,权限信息不保留。

zip 命令默认不递归压缩子目录
直接 zip archive.zip dir/ 只会把空目录结构加进去,里面文件一个都不在。这是新手最常踩的坑——看着命令跑完了,解压出来却是空文件夹。
必须显式加上 -r 参数才能递归打包:
zip -r archive.zip dir/
- 没加
-r:只存目录名,不存内容 - 加了
-r:遍历所有子目录和文件,正常打包 - 如果只想打包当前目录下文件(不含子目录),就别用
-r,但这种情况极少
中文文件名乱码或解压失败
Linux 的 zip 默认用 CP437 编码写入文件名,而中文系统多用 UTF-8。结果就是 Windows 或 macOS 解压时显示一堆问号或方块。
解决办法不是改系统 locale,而是让 zip 用 UTF-8 写入(需较新版本,≥ 3.0):
zip -r -UN=UTF8 archive.zip dir/
-
-U启用 Unicode 文件名支持 -
-N强制使用指定编码,UTF8是字面量,不能写成utf-8或小写 - 老版本 zip(如 CentOS 7 自带的 3.0 以下)不支持
-UN,只能靠解压端转码,不可靠
排除不需要的文件(比如 .git、__pycache__)
zip 没有类似 tar --exclude 那样简洁的排除语法,得靠 -x 手动列模式,而且路径匹配很敏感。
正确写法示例(排除 .git 和所有 __pycache__ 目录):
zip -r archive.zip src/ -x "*.git*" "*__pycache__*"
-
-x后面的模式是 shell glob,不是正则;*匹配任意字符,**不生效 - 路径要和 zip 命令里实际传入的路径层级一致:如果打包的是
./src/,那-x里写"src/__pycache__/*"才有效 - 多个排除项之间用空格分隔,每个都得加引号防 shell 展开
zip 压缩率低且不支持多线程
原生命令 zip 默认用 DEFLATE 算法,压缩率比 zstd 或 lzma 差不少,而且无法利用多核加速。
如果对体积或速度有要求,别硬扛 zip:
- 要兼容性(比如发给 Windows 用户):用
zip -9 -r archive.zip dir/开最高压缩级,但别指望翻倍缩小 - 只要 Linux/macOS 自用:直接换
tar -cf - dir/ | zstd -T0 -o archive.tar.zst,快得多,也小得多 -
zip的-0到-9只影响压缩时间/体积权衡,不影响解压兼容性
真正麻烦的是:zip 格式本身不记录文件所有者和权限位,解压后得手动 chmod。这点容易被忽略,尤其部署脚本里依赖执行权限时会静默失败。










