我有一个程序,需要在其中将文件夹内容(从folder1)复制到folder2同一目录级别(路径)中的新文件夹()。由于无法提供相同的名称,因此我使用tmpFolder名称(用于folder2)。完成所有逻辑后,需要压缩复制的文件夹,并给zip命名folder1.zip ,问题是当我解压缩时folder1.zip 看到folder2。
folder1
folder2
folder1.zip
我希望它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的标头。这很重要,因为它会填充诸如时间戳和未压缩大小的元数据。
此外,您的代码似乎正在执行以下操作:
如果通过以下方式调用:
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。
/path/to/folder2/otherdir/myfile
folder2/otherdir/myfile
如果要更改存储在存档中的目录名称,只需更改baseDir为所需的名称。
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/。
folder1/