所以我试图从多个目录和文件创建一个tar.gz文件。具有与以下用法相同的用法:
tar -cvzf sometarfile.tar.gz somedir/ someotherdir/ somefile.json somefile.xml
假设目录中还有其他目录。我将其作为输入:
paths := []string{
"somedir/",
"someotherdir/",
"somefile.json",
"somefile.xml",
}
并使用这些:
func TarFilesDirs(paths []string, tarFilePath string ) error {
// set up the output file
file, err := os.Create(tarFilePath)
if err != nil {
return err
}
defer file.Close()
// set up the gzip writer
gz := gzip.NewWriter(file)
defer gz.Close()
tw := tar.NewWriter(gz)
defer tw.Close()
// add each file/dir as needed into the current tar archive
for _,i := range paths {
if err := tarit(i, tw); err != nil {
return err
}
}
return nil
}
func tarit(source string, tw *tar.Writer) error {
info, err := os.Stat(source)
if err != nil {
return nil
}
var baseDir string
if info.IsDir() {
baseDir = filepath.Base(source)
}
return filepath.Walk(source,
func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
header, err := tar.FileInfoHeader(info, info.Name())
if err != nil {
return err
}
if baseDir != "" {
header.Name = filepath.Join(baseDir, strings.TrimPrefix(path, source))
}
if err := tw.WriteHeader(header); 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(tw, file)
if err != nil {
log.Println("failing here")
return err
}
return err
})
}
问题:如果目录很大,我将得到:
archive/tar: write too long
错误,当我将其删除时,一切正常。
花了很多时间在寻找解决方案上的想法...
有任何想法吗?
谢谢
在我更仔细地查看tar.FileInfoHeader doc之前,我遇到了类似的问题:
FileInfoHeader从fi创建一个部分填充的Header。如果fi描述了符号链接,则FileInfoHeader会将链接记录为链接目标。如果fi描述目录,则名称后会加上斜杠。由于os.FileInfo的Name方法仅返回其描述的文件的基本名称,因此可能有必要修改返回的标头的Name字段以提供文件的完整路径名。
本质上,在使用WriteHeader编写文件之前,不保证FileInfoHeader会填写所有标头字段,并且如果您查看实现,则Size字段仅在常规文件上设置。您的代码段似乎仅处理目录,这意味着如果遇到任何其他非常规文件,则将头的大小写为零,然后尝试将磁盘上大小可能为非零的特殊文件复制到tar中。Go返回ErrWriteTooLong以阻止您创建损坏的tar。
我想到了这一点,此后就再也没有问题了。
if err := filepath.Walk(directory, func(path string, info os.FileInfo, err error) error {
if err != nil {
return check(err)
}
var link string
if info.Mode()&os.ModeSymlink == os.ModeSymlink {
if link, err = os.Readlink(path); err != nil {
return check(err)
}
}
header, err := tar.FileInfoHeader(info, link)
if err != nil {
return check(err)
}
header.Name = filepath.Join(baseDir, strings.TrimPrefix(path, directory))
if err = tw.WriteHeader(header); err != nil {
return check(err)
}
if !info.Mode().IsRegular() { //nothing more to do for non-regular
return nil
}
fh, err := os.Open(path)
if err != nil {
return check(err)
}
defer fh.Close()
if _, err = io.CopyBuffer(tw, fh, buf); err != nil {
return check(err)
}
return nil
})
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句