小编典典

解压缩具有不同名称的工件

go

我有一个程序,需要在其中将文件夹内容(从folder1)复制到folder2同一目录级别(路径)中的新文件夹()。由于无法提供相同的名称,因此我使用tmpFolder名称(用于folder2)。完成所有逻辑后,需要压缩复制的文件夹,并给zip命名folder1.zip
,问题是当我解压缩时folder1.zip 看到folder2

我希望它folder1在拉链之后。

我可以使用一些技巧吗?

另外,我知道我可以复制到不同级别(路径)的folder2中,但是我想尽可能避免复制,因为在处理大文件夹内容时副本可能非常昂贵。

我使用以下代码压缩文件夹:

func Zipit(source, target string) error {
    zipfile, err := os.Create(target)
    if err != nil {
        return err
    }
    defer zipfile.Close()

    archive := zip.NewWriter(zipfile)
    defer archive.Close()

    info, err := os.Stat(source)
    if err != nil {
        return nil
    }

    var baseDir string
    if info.IsDir() {
        baseDir = filepath.Base(source)
    }

    filepath.Walk(source, func(path string, info os.FileInfo, err error) error {
        if err != nil {
            return err
        }

        header, err := zip.FileInfoHeader(info)
        if err != nil {
            return err
        }

        if baseDir != "" {
            header.Name = filepath.Join(baseDir, strings.TrimPrefix(path, source))
        }

        if info.IsDir() {
            header.Name += "/"
        } else {
            header.Method = zip.Deflate
        }

        writer, err := archive.CreateHeader(header)
        if err != nil {
            return err
        }

        if info.IsDir() {
            return nil
        }

        file, err := os.Open(path)
        if err != nil {
            return err
        }
        defer file.Close()
        _, err = io.Copy(writer, file)
        return err
    })

    return err
}

阅读 270

收藏
2020-07-02

共1个答案

小编典典

zip存档中文件和目录的名称来自zip.FileHeader

您的代码已经初始化了os.FileInfo的标头。这很重要,因为它会填充诸如时间戳和未压缩大小的元数据。

此外,您的代码似乎正在执行以下操作:

如果通过以下方式调用:

Zipit("/path/to/folder2/", "/path/to/folder1.zip")

在遍历目录树之前,它将计算基本目录:

baseDir = filepath.Base(source)
// baseDir is "folder2"

然后,对于每个文件,存档内的路径设置为:

header.Name = filepath.Join(baseDir, strings.TrimPrefix(path, source))

这样会将文件名/path/to/folder2/otherdir/myfile转换为folder2/otherdir/myfile

如果要更改存储在存档中的目录名称,只需更改baseDir为所需的名称。

我建议以下解决方案:

将功能签名更改为:

func Zipit(source, target, newBaseName string) error {

将basedir更改为:

if newBaseName != "" {
    baseDir = newBaseName
else if info.IsDir() {
    baseDir = filepath.Base(source)
}

然后使用以下命令调用函数:

Zipit("/path/to/folder2/", "/path/to/folder1.zip", "folder1")

这应导致将存档解压缩到中folder1/

2020-07-02