2016-09-22 8 views
1

tarballのheaderinfoにディレクトリを書き込む方法がわかりません。たとえば、私は次のディレクトリ構造を持っています。Golang tarring directory

test [dir] 
-- test1.txt 
    -- subDirA [sub dir] 
     -- test2.txt 

Goタール実行可能ファイルを使って私がタールアップテストを行った場合、そのファイルは元の構造になります。私はtarボールの上にタールを-tvf行う場合、リストは次のようになります。私は手動テストの-cvfタールを行い、その後、-tvfタールをすれば

test/test1.txt 
test/subDirA/test2.txt 

しかし、リストは次のようになります。

test/ 
test/test1.txt 
test/subDirA/ 
test/subDirA/test2.txt 

これは私のGoタールリングプログラムにも同様にしたいものです。私のGoプログラムでは、新しいメソッドwriteDirToTarを追加して、ディレクトリをtarWriterに追加しようとしました。私は、fileWalk関数からwriteFileToTarまたはwriteDirToTarを呼び出します。 writeDirToTario.Copy(tarWriter, file)を呼び出すと、「テスト/サブディレクトリがディレクトリです」というエラーが発生します。どのような意味がありますか。このための回避策はありますか?

func writeToTar(fileDir string, 
     sourceBase string, 
     tarWriter *tar.Writer, 
     f os.FileInfo) error { 

     file, err := os.Open(fileDir) 
     if err != nil { 
       log.Print("error opening file") 
       return err 
     } 
     defer file.Close() 

     // relative paths are used to preserve the directory paths in each file path 
     relativePath, err := filepath.Rel(sourceBase, fileDir) 

     tarheader := new(tar.Header) 
     tarheader.Name = relativePath 
     tarheader.Size = f.Size() 
     tarheader.Mode = int64(f.Mode()) 
     tarheader.ModTime = f.ModTime() 

     err = tarWriter.WriteHeader(tarheader) 
     if err != nil { 
       log.Print("error writing tarHeader") 
       return err 
     } 
     _, err = io.Copy(tarWriter, file) 
     if err != nil { 
       log.Print("error writing to tarWriter") 
       return err 
     } 
     return nil 
} 

func writeDirToTar(fileDir string, 
     sourceBase string, 
     tarWriter *tar.Writer, 
     f os.FileInfo) error { 

     file, err := os.Open(fileDir) 
     if err != nil { 
       log.Print("error opening file") 
       return err 
     } 
     defer file.Close() 

     // relative paths are used to preserve the directory paths in each file path 
     relativePath, err := filepath.Rel(sourceBase, fileDir) 

     if tarHeader, err := tar.FileInfoHeader(f, relativePath); err != nil { 
       log.Print("error writing tarHeader") 
       return err 
     } 

     tarHeader.Name = relativePath 
     tarheader.Mode = int64(f.Mode()) 
     tarheader.ModTime = f.ModTime() 

     _, err = io.Copy(tarWriter, file) 
     if err != nil { 
       log.Print("error writing to tarWriter") 
       return err 
     } 
     return nil 

} 

答えて

1

あなたはtar.HeaderTypeflagフィールドを逃しています。あなたは、少なくともたいと思うディレクトリについては

tarheader := &tar.Header{ 
    Name:  relativePath, 
    Mode:  int64(f.Mode()), 
    ModTime: f.ModTime(), 
    Typeflag: tar.TypeDir, 
} 

内部ディレクトリデータ構造はタールに何も意味しないので、あなたがここにサイズをしたくない、でもあなたは、ディレクトリのデータをコピーしたいです。

ファイル名に/を追加して、ファイル名がディレクトリであることを視覚的に示し、POSIXのtarの動作と一致させることもできます。

また、適切なヘッダー構造を作成するためにファイルと同じようにtar.FileInfoHeader関数を使用することもできます。