简单介绍及说明

golang代码可以tar 目录和文件的,并且tar包是以要打包的文件或者目录名字命名tar包,如果是打包目录,目录结构和里面的文件也可以递归打包

如下面示例代码tar.go中

sourceDir := "/root/test_tar/"
targetDir := "/root/test_untar/"

sourceTar := "/root/test_untar/test_tar.tar.gz"
targetUnTarDir := "/root/test_untar/"

打包:我将test_tar打包成test_tar.tar.gz保存在/root/test_untar/

解包:我将刚才打包的/root/test_untar/test_tar.tar.gz解包到/root/test_untar/

提示:目标目录不可以包含在源目录内,否则会造成递归打包

解压到保存目录必须是个目录

代码示例 tar.go
package main

import (
        "archive/tar"
        "fmt"
        "io"
        "os"
        "path/filepath"
        "strings"
)

func Tar(source, target string) error {
        filename := filepath.Base(source)
        target = filepath.Join(target, fmt.Sprintf("%s.tar.gz", filename))

        tarfile, err := os.Create(target)
        if err != nil {
                return err
        }
        defer tarfile.Close()

        tarball := tar.NewWriter(tarfile)
        defer tarball.Close()

        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 := tarball.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(tarball, file)
                        return err
                })
}

func UnTar(tarball, target string) error {
        reader, err := os.Open(tarball)
        if err != nil {
                return err
        }
        defer reader.Close()
        tarReader := tar.NewReader(reader)

        for {
                header, err := tarReader.Next()
                if err == io.EOF {
                        break
                } else if err != nil {
                        return err
                }

                path := filepath.Join(target, header.Name)
                info := header.FileInfo()
                if info.IsDir() {
                        if err = os.MkdirAll(path, info.Mode()); err != nil {
                                return err
                        }
                        continue
                }

                file, err:= os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, info.Mode())
                if err != nil {
                        return err
                }
                defer file.Close()
                _, err =io.Copy(file, tarReader)
                if err != nil {
                        return err
                }
        }
        return nil
}


func main() {


        sourceDir := "/root/test_tar/"
        targetDir := "/root/test_untar/"

        if err := Tar(sourceDir, targetDir); err != nil {
                fmt.Printf("tar failed %s\n", err.Error())
        }


        sourceTar := "/root/test_untar/test_tar.tar.gz"
        targetUnTarDir := "/root/test_untar/"

        if err := UnTar(sourceTar,targetUnTarDir); err != nil {
                fmt.Printf("Untar failed %s\n",err.Error())
        }


}
程序测验

程序执行前:

执行go run tar.go之后