在使用Golang压缩目录时,tar命令会为目录或文件设置typeflag。

huangapple go评论72阅读模式
英文:

tar typeflag directory or file when tar'ing directories in golang

问题

我不确定如何在对包含文件和子目录的目录进行tar操作时设置Header.Typeflag。我知道如果我添加

header.Typeflag = '0'

它只会打包文件而不包括目录。当文件或目录时,我该如何设置Typeflag,以便在解压时可以将其传递给tar.TypeDir中的case语句?

以下是从https://www.socketloop.com/tutorials/golang-archive-directory-with-tar-and-gzip中提取的示例代码:

package main

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

func checkerror(err error) {
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
}

func main() {
    flag.Parse() // 从命令行获取参数

    destinationfile := flag.Arg(0)

    if destinationfile == "" {
        fmt.Println("Usage : gotar destinationfile.tar.gz source")
        os.Exit(1)
    }

    sourcedir := flag.Arg(1)

    if sourcedir == "" {
        fmt.Println("Usage : gotar destinationfile.tar.gz source-directory")
        os.Exit(1)
    }

    dir, err := os.Open(sourcedir)

    checkerror(err)

    defer dir.Close()

    files, err := dir.Readdir(0) // 获取文件列表

    checkerror(err)

    tarfile, err := os.Create(destinationfile)

    checkerror(err)

    defer tarfile.Close()
    var fileWriter io.WriteCloser = tarfile

    if strings.HasSuffix(destinationfile, ".gz") {
        fileWriter = gzip.NewWriter(tarfile) // 添加gzip过滤器
        defer fileWriter.Close()            // 如果用户在目标文件名中添加了.gz
    }

    tarfileWriter := tar.NewWriter(fileWriter)
    defer tarfileWriter.Close()

    for _, fileInfo := range files {
        if fileInfo.IsDir() {
            continue
        }

        // 参考:https://www.socketloop.com/tutorials/go-file-path-independent-of-operating-system
        file, err := os.Open(dir.Name() + string(filepath.Separator) + fileInfo.Name())

        checkerror(err)

        defer file.Close()

        // 准备tar头部
        header := new(tar.Header)
        header.Name = file.Name()
        header.Size = fileInfo.Size()
        header.Mode = int64(fileInfo.Mode())
        header.ModTime = fileInfo.ModTime()

        err = tarfileWriter.WriteHeader(header)

        checkerror(err)

        _, err = io.Copy(tarfileWriter, file)

        checkerror(err)
    }
}
英文:

I'm not sure how to set Header.Typeflag when tar'ing a directory with files and subdirectories. I know if I add

header.Typeflag = '0'

It will only tar files but not directories. How do I set the Typeflag when it is a file or directory so when untar'ing I can pass it in a case statement to tar.TypeDir

Example taken from https://www.socketloop.com/tutorials/golang-archive-directory-with-tar-and-gzip

package main
import (
"archive/tar"
"compress/gzip"
"flag"
"fmt"
"io"
"os"
"strings"
"path/filepath"
)
func checkerror(err error) {
if err != nil {
fmt.Println(err)
os.Exit(1)
}
}
func main() {
flag.Parse() // get the arguments from command line
destinationfile := flag.Arg(0)
if destinationfile == "" {
fmt.Println("Usage : gotar destinationfile.tar.gz source")
os.Exit(1)
}
sourcedir := flag.Arg(1)
if sourcedir == "" {
fmt.Println("Usage : gotar destinationfile.tar.gz source-directory")
os.Exit(1)
}
dir, err := os.Open(sourcedir)
checkerror(err)
defer dir.Close()
files, err := dir.Readdir(0) // grab the files list
checkerror(err)
tarfile, err := os.Create(destinationfile)
checkerror(err)
defer tarfile.Close()
var fileWriter io.WriteCloser = tarfile
if strings.HasSuffix(destinationfile, ".gz") {
fileWriter = gzip.NewWriter(tarfile) // add a gzip filter
defer fileWriter.Close()            // if user add .gz in the destination filename
}
tarfileWriter := tar.NewWriter(fileWriter)
defer tarfileWriter.Close()
for _, fileInfo := range files {
if fileInfo.IsDir() {
continue
}
// see https://www.socketloop.com/tutorials/go-file-path-independent-of-operating-system
file, err := os.Open(dir.Name() + string(filepath.Separator) + fileInfo.Name())
checkerror(err)
defer file.Close()
// prepare the tar header
header := new(tar.Header)
header.Name = file.Name()
header.Size = fileInfo.Size()
header.Mode = int64(fileInfo.Mode())
header.ModTime = fileInfo.ModTime()
err = tarfileWriter.WriteHeader(header)
checkerror(err)
_, err = io.Copy(tarfileWriter, file)
checkerror(err)
}
}

答案1

得分: 1

如果文件在磁盘上,看起来是这样的,那么这部分工作已经为您完成了。请查看FileInfoHeader。根据资源(在您的情况下是目录或文件)可以推断出的信息,它将设置Typeflag。

有关可用选项的完整列表,请参阅tar标准文档

英文:

If the files are on disk, which it looks like they are, then that part is done for you. Have a look at FileInfoHeader. That will set the Typeflag based on what it can extrapolate from the resource (directory or file in your case.)

For a complete list of the available options see the tar standard docs

huangapple
  • 本文由 发表于 2015年8月31日 12:10:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/32303873.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定