From f6f22ecaf69f0853f4736a6786b3c388ba994139 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=97=E5=AD=90?= Date: Fri, 8 May 2026 17:37:02 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20zip=20=E8=A7=A3=E5=8E=8B=E6=94=B9?= =?UTF-8?q?=E7=94=A8=207z=20=E5=A4=84=E7=90=86=E4=B8=AD=E6=96=87=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit unzip 默认按 UTF-8 解析文件名,Windows GBK/CP936 编码的 zip 包会被转义成 #Uxxxx 形式 改用 7z x 替代,自动检测文件名编码 Co-Authored-By: Claude Opus 4.7 (1M context) --- pkg/io/compress.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pkg/io/compress.go b/pkg/io/compress.go index 156855f9..fdfe92f3 100644 --- a/pkg/io/compress.go +++ b/pkg/io/compress.go @@ -75,7 +75,8 @@ func UnCompress(src string, dst string) error { switch format { case Zip: - _, err = shell.Execf("unzip -qo '%s' -d '%s'", src, dst) + // 用 7z 解压 zip,自动检测文件名编码,避免中文文件名变成 #Uxxxx + _, err = shell.Execf("7z x -y '%s' -o'%s'", src, dst) case Gz: // 单独的 gzip 文件(如 .sql.gz),解压到目标目录 // gunzip -k 保留原文件,-c 输出到标准输出,重定向到目标文件 @@ -107,16 +108,14 @@ func ListCompress(src string) ([]string, error) { var out string switch format { - case Zip: - out, err = shell.Execf("unzip -Z1 '%s'", src) + case Zip, SevenZip: + out, err = shell.Execf(`7z l -ba -slt '%s' | grep "^Path = " | sed 's/^Path = //'`, src) case Gz: // 单独的 gzip 文件只包含一个文件,返回去除 .gz 后缀的文件名 baseName := strings.TrimSuffix(filepath.Base(src), ".gz") return []string{baseName}, nil case TGz, Bz2, Tar, Xz: out, err = shell.Execf("tar -tf '%s'", src) - case SevenZip: - out, err = shell.Execf(`7z l -ba -slt '%s' | grep "^Path = " | sed 's/^Path = //'`, src) default: return nil, errors.New("unsupported format") }