Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
4.1k views
in Technique[技术] by (71.8m points)

go 写了tar打包的程序,但是目录结构丢失

本来想配一个图,但是xx的上传失败。 我简单描述一些就是本来打包一个有子文件夹的。 但是打包后都在root目录下(实在tar格式文件的,root目录)

/*
描述: Cherry
作者:剑仙兰陵
时间: 2020/11/9 - 17:46
邮箱: yi-kylin@outlook.com
文件: File.go
*/
package Choreser
import (
   "archive/tar"
 "fmt" "io" "os" "path/filepath" "syscall")
type FileType int
const (
   PATH_NIL FileType = 0
 PATH_DIR FileType = 1
 PATH_FILE FileType = 2
 PATH_OTHER FileType = 3
)
type FileState int
const (
   Untreated FileState= 0
 Ignore FileState= 1
 Tared FileState= 2
 Fail FileState= 3
)
type Filemate struct {
   Ft FileType
 Fs FileState
 Error error
}
/**  [康子·肆柒壹柒 ? 鼠]
* @MethodName: FileType
* @param: f os.FileInfo
* @Return: filetype
* @Description: 返回文件类型描述filetype,
 win回收站以PATH_OTHER处理
 linux,macos, linux 平台还没有完善
 fileinfo,_ := fs.Stat() FileType(fileinfo)
* @author: Maple-huang 剑仙兰陵
* @email: yi-kylin@outlook.com
* @date: 2020/11/18 12:29
*/
func GetFileType(fi os.FileInfo)  FileType{
   if fi == nil {
      return PATH_NIL
 }
   //windows的系统回收站, Linux和mac场景没有补全哦
 if fi.Sys().(*syscall.Win32FileAttributeData).FileAttributes == 22 {
      return PATH_OTHER
 }
   if fi.Mode().IsDir() {
      return PATH_DIR
 } else if fi.Mode().IsRegular() {
      return PATH_FILE
 }else{
      return PATH_OTHER
 }
}
/**  [康子·肆柒壹柒 ? 鼠]
* @MethodName: FileNotExist
* @param: path string 文件路径
* @Return: 如果由 filename 指定的文件或目录存在则返回 true,否则返回 false* @Description: 检查文件或目录是否存在
* @author: Maple-huang 剑仙兰陵
* @email: yi-kylin@outlook.com
* @date: 2020/11/12 11:36
*/
func FileExist(path string) bool {
   _, err := os.Stat(path)
   return err == nil || os.IsExist(err)
}
/**  [康子·肆柒壹柒 ? 鼠]
* @MethodName:
* @param:
* @Return:
* @Description:
* @author: Maple-huang 剑仙兰陵
* @email: yi-kylin@outlook.com
* @date: 2020/11/23 20:40
*/
func Tar(sourcePath, tarPath string) error {
   if !FileExist(sourcePath) {
      return fmt.Errorf("源文件 %s 不存在", sourcePath)
   }
   //覆盖,需要外部判断
 if FileExist(tarPath) {
      if err:=os.Remove(tarPath); err != nil {
         return fmt.Errorf("测试旧压缩文件%s, 发生%w", sourcePath, err)
      }
   }
   if tarDirPath := filepath.Dir(tarPath); !FileExist(tarDirPath) {
      if err:=os.MkdirAll(tarDirPath, 0760); err != nil {
         return fmt.Errorf("创建压缩文件时%s, 发生%w", sourcePath, err)
      }
   }
   tarf, openTarfErr:= os.Create(tarPath)
   tw := tar.NewWriter(tarf)
   if openTarfErr != nil {
      println("####", tarPath, openTarfErr.Error())
      return fmt.Errorf("打开压缩文件 %w", openTarfErr)
   }
   defer tarf.Close()
   defer tw.Close()
   println("$$", tarPath )
   println("$$", sourcePath )
   var tarfiles  map[string]Filemate
 tarfiles = make(map[string]Filemate)
   filepath.Walk(sourcePath, func(p string, info os.FileInfo, err error) error {
      fm := Filemate{PATH_NIL,Untreated, err}
      println("@", p)
      switch GetFileType(info) {
      case PATH_FILE:
         err := TarFile(p, info, tw)
         if err != nil{
            println(err.Error())
         }
         fm.Ft = PATH_FILE
 case PATH_DIR:
         err := TarDir(p, info, tw)
         if err != nil{
            println(err.Error())
         }
         fm.Ft = PATH_DIR
 case PATH_NIL:
         fm.Ft = PATH_NIL
 println("未知", p)
      case PATH_OTHER:
         fm.Ft = PATH_OTHER
 println("其他", p)
      }
      tarfiles[p] = fm
      return err
   })
   return nil
}
func TarFile(p string, info os.FileInfo, tw *tar.Writer)  error {
   f,e := os.Open(p)
   defer f.Close()
   if e!=nil {
      return fmt.Errorf("打开文件时 %w", e)
   }
   if hdr, err :=     tar.FileInfoHeader(info, ""); err!=nil{
      return err
   }else{
      hdr.Format = tar.FormatGNU
 if err = tw.WriteHeader(hdr); err!= nil {
         return fmt.Errorf("写入文件头部时 %w", err)
      }
   }
   if _, e:=io.Copy(tw, f); e!=nil {
      return e
   }
   return nil
}
func TarDir(p string, info os.FileInfo, tw *tar.Writer)  error {
   println("Dir")
   last := len(p) - 1
 if p[last] != os.PathSeparator {
      p += string(os.PathSeparator)
   }
   f,e := os.Open(p)
   defer f.Close()
   if e!=nil {
      return fmt.Errorf("打开文件时 %w", e)
   }
   if hdr, err :=     tar.FileInfoHeader(info, ""); err!=nil{
      return err
   }else{
      hdr.Format = tar.FormatGNU
 if err = tw.WriteHeader(hdr); err!= nil {
         return fmt.Errorf("写入文件夹头部时 %w", err)
      }
   }
   return nil
}

写个测试文件就能跑


/*
描述: Cherry
作者:剑仙兰陵
时间: 2020/11/9 - 17:46
邮箱: yi-kylin@outlook.com
文件: File.go
*/
package Choreser
import (
   "testing"
)
func TestTar(t *testing.T)  {
   Tar(
      "E:色图杂物",
 "C:codego_codeCherrySnapshot杂物.tar",
 )
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
等待大神解答

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...