dongqing344716 2012-11-28 17:36
浏览 73
已采纳

如何将目录(不仅仅是其中的文件)写入golang中的tar.gz文件

I want to write a tar_gz tool in Go. The input is just like linux command:

$tar czvf targetFileName inputDirectoryPath

Suppose I have an inputDirectory structured as below:

test [dir]
-- 0.txt
    -- 1 [sub dir]
         -- 1.txt

For Example: use command:

$tar czvf test.tar.gz test/

we can tar and gzip the whole test directory.


My Problem is I can write a tar and gz route to recursively iterate all the file in test directory and write the file to test.tar.gz file. But I don't know how to write a directory to the test.tar.gz. After running my program, the structure in test.tar.gz file is:

0.txt
1.txt

Can anyone tell me how to write the directory recursively to the output tar.gz file. Thanks a lot.

    package main

    import (
      "fmt"
      "os"
      "io"
      "log"
      "strings"
      "archive/tar"
      "compress/gzip"
    )

    func handleError( _e error ) {
      if _e != nil {
        log.Fatal( _e )
      }
    }

    func TarGzWrite( _path string, tw *tar.Writer, fi os.FileInfo ) {
      fr, err := os.Open( _path )
      handleError( err )
      defer fr.Close()

      h := new( tar.Header )
      h.Name = fi.Name()
      h.Size = fi.Size()
      h.Mode = int64( fi.Mode() )
      h.ModTime = fi.ModTime()

      err = tw.WriteHeader( h )
      handleError( err )

      _, err = io.Copy( tw, fr )
      handleError( err )
    }

    func IterDirectory( dirPath string, tw *tar.Writer ) {
      dir, err := os.Open( dirPath )
      handleError( err )
      defer dir.Close()
      fis, err := dir.Readdir( 0 )
      handleError( err )
      for _, fi := range fis {
        curPath := dirPath + "/" + fi.Name()
        if fi.IsDir() {
          //TarGzWrite( curPath, tw, fi )
          IterDirectory( curPath, tw )
        } else {
          fmt.Printf( "adding... %s
", curPath )
          TarGzWrite( curPath, tw, fi )
        }
      }
    }

    func TarGz( outFilePath string, inPath string ) {
      // file write
      fw, err := os.Create( outFilePath )
      handleError( err )
      defer fw.Close()

      // gzip write
      gw := gzip.NewWriter( fw )
      defer gw.Close()

      // tar write
      tw := tar.NewWriter( gw )
      defer tw.Close()

      IterDirectory( inPath, tw )

      fmt.Println( "tar.gz ok" )
    }

    func main() {
      targetFilePath := "test.tar.gz"
      inputDirPath := "test/"
      TarGz( targetFilePath, strings.TrimRight( inputDirPath, "/" ) )
      fmt.Println( "Hello, World" )
    }
  • 写回答

2条回答 默认 最新

  • doupingmao1903 2012-11-28 18:22
    关注

    You're only adding the filename to the tar, not the entire path. You need to keep the whole path for Tar to be able to understand directories. You just need to change one line:

    h.Name = fi.Name()
    

    Should be:

    h.Name = _path
    

    On Linux, the output of tar -tvf test.tar.gz:

    -rw-rw-r-- 0/0               0 2012-11-28 11:17 test/0.txt
    -rw-rw-r-- 0/0               0 2012-11-28 11:17 test/sub/1.txt
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?