本来想配一个图,但是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",
)
}