GolangのDockerクライアントでコンテナにファイルを送る際、tarファイルを作成する必要があったため、調べました。
プログラム
まずは結論から、以下のようなプログラムでtarを作成出来ます。
今回のサンプルでは以下を実装してみました。
- ディスク上のファイルをtarに追加する。
- 変数の中のデータ(文字列)をtarに追加する。
package main import ( "archive/tar" "fmt" "io" "os" "time" ) func main() { //1. tarファイルの作成 tarFile, err := os.Create("dest/archive.tar") if err != nil { fmt.Println("tarファイルが作成できなかった。") return } //2. tarWriterを作成 tarWriter := tar.NewWriter(tarFile) defer tarWriter.Close() //3. ディスク上のファイルをtarに追加する。 file, err := os.Open("src/hoge.txt") if err != nil { fmt.Println("ファイルが開けなかった。") return } stat, err := file.Stat() if err != nil { fmt.Println("ファイルの状態が取得できなかった。") return } header := &tar.Header{ Name: "hoge.txt", //ここでsrc/hoge.txtと指定すると、解答時にそのPATHになる。 Mode: int64(stat.Mode()), ModTime: stat.ModTime(), Size: stat.Size(), } err = tarWriter.WriteHeader(header) if err != nil { fmt.Errorf("headerを書き込めなかった") return } _, err = io.Copy(tarWriter, file) if err != nil { fmt.Errorf("ファイルをコピー出来なかった") return } //4. 変数のデータをtarに追加する data := "Hello world!!" header = &tar.Header{ Name: "data/hello.txt", Mode: 0644, ModTime: time.Now(), Size: int64(len(data)), } err = tarWriter.WriteHeader(header) if err != nil { fmt.Errorf("headerを書き込めなかった") return } _, err = tarWriter.Write([]byte(data)) if err != nil { fmt.Println("tarに書き込めなかった") } }
解説
まずは、tarファイルを作成、そのtarに書き込むためのWriterを取得します。
//1. tarファイルの作成 tarFile, err := os.Create("dest/archive.tar") if err != nil { fmt.Println("tarファイルが作成できなかった。") return } //2. tarWriterを作成 tarWriter := tar.NewWriter(tarFile) defer tarWriter.Close()
ここまではシンプルですね。
つぎにheaderを作成してwriter経由で書き込み
ます。
header := &tar.Header{ Name: "hoge.txt", //解凍時のパスになる Mode: int64(stat.Mode()), // 0644など定数も指定できる。 ModTime: stat.ModTime(), // 最終更新時刻 Size: stat.Size(), // 正しいサイズを指定する! }
Name
には、tarに格納するファイル名を指定します。
Nameにdata/hoge.txt
という風にパスを指定すると、解凍時にはdata
ディレクトリが作成されます。
そのほか、Mode
や ModTime
など指定します。
特に、Sizeは正しく指定しないと tarWriter.Write()
でエラーになります。
この辺は公式のドキュメントを参照してください。
最後に、tarに実際のデータを追加します。
// ファイルをtarの中にコピーする場合 _, err = io.Copy(tarWriter, file) if err != nil { fmt.Errorf("ファイルをコピー出来なかった") return }
また、変数の中身をファイルとして出力することも出来ます。
_, err = tarWriter.Write([]byte(data))
このプログラムを実行すると、 archive.tar
というファイルが dest
フォルダの中にできます。
これを解凍すると、以下のようになります。
. └── archive ├── data │ └── hello.txt └── hoge.txt
Golangでたくさんtarを作りましょう!!!
リンク
このプログラムのGist版
How to create tar file in Golang · GitHub