我有一个程序,我需要在其中将文件夹内容(从 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
}
最佳答案
zip 存档中的文件和目录名称来自 zip.FileHeader .
您的代码已经从 os.FileInfo 初始化了 header .这很重要,因为它会填充元数据,例如时间戳和未压缩的大小。
此外,您的代码似乎在执行以下操作:
如果调用:
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/
中。
关于go - 解压具有不同名称的工件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48732412/