解压缩具有不同名称的工件 [英] Unzip artifacts with different name

查看:143
本文介绍了解压缩具有不同名称的工件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



我希望它在zip之后是 folder1



有没有我可以用它来做这件事吗?另外,我知道我可以复制到不同级别的文件夹(路径),但我想避免它,如果可能的话,因为
的副本可以是非常当使用大文件夹内容时,价格昂贵。



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

  func Zipit(source,target string)错误{
zipfile,err:= os.Create(target)
if err!= nil {
return err
}
推迟zipfile.Close()

存档:= zip.NewWriter(zipfile)
推迟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 {
如果err!= nil {
return err
}

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

if baseDir!={
header.Name = filepath.Join(baseDir,strings.TrimPrefix(来源))
}

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
}
推迟file.Close()
_,err = io.Copy(writer,file)
return err
$)

return err
}


解决方案

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



您的代码已经从 os.FileInfo 。这一点很重要,因为它填充了时间戳和未压缩大小等元数据。



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



如果使用:

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

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

  baseDir = filepath.Base(源)
// baseDir是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)
}

然后调用你的函数:


$ b $

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

这会导致归档文件解压到 folder1 /


I have a program in which I need to copy the folder contents (from folder1) to a new folder (folder2) in the same dir level (path). Since I cannot give the same name I use tmpFolder name (for folder2). When I finish to do all the logic I need zip the copied folder and I give the zip the name folder1.zip The problem is that when I extract the folder1.zip I see folder2.

I want it to be folder1 after the zip.

Is there some trick I can use to do it?

In addition, I know that I can copy to folder2 in different level (path) but I want to avoid it if possible since the copy can be very expensive when working on big folder contents.

I use this code to zip the folder:

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
}

解决方案

Names of files and directories in zip archives come from the zip.FileHeader.

Your code already initializes the header from the os.FileInfo. This is important as it populates metadata such as timestamps and uncompressed size.

Furthermore, your code seems to be doing the following:

If invoked with:

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

Before traversing the directory tree, it computes the base directory:

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

Then for each file, the path inside the archive is set to:

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

This turns a filename such as /path/to/folder2/otherdir/myfile into folder2/otherdir/myfile.

If you want to change the directory name stored inside the archive, you just need to change baseDir to the desired name.

I would recommend the following solution:

Change the function signature to:

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

Change the basedir to:

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

Then call your function with:

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

This should result in an archive that extracts into folder1/.

这篇关于解压缩具有不同名称的工件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆