5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

tar ファイルを単に cat でつなげてしまっても GNU の tar なら読めるよ

Last updated at Posted at 2015-07-16

こんな風に tar ファイルを cat でつなげてしまったとする。

$ touch A
$ touch B
$ touch C
$ touch D
$ tar -cf AB.tar A B
$ tar -cf CD.tar C D
$ cat AB.tar CD.tar > ABCD.tar

これを tar の -t オプションでファイルをリストアップしてみると

$ tar -tf ABCD.tar
実行結果
A
B

後ろにつなげた C ファイルと D ファイルは認識されてない!
そりゃ単に cat で繋げちゃったら認識しなそうな気もするよね!

でも GNU tar ならできちゃう

ところがそんな時も GNU tar なら -i (--ignore-zeros) オプションがあるから大丈夫

$ tar -itf ABCD.tar
実行結果
A
B
C
D

なんと、 cat でつなげただけの後ろの tar もちゃんと読めるのだ!

残念なことに、この便利なオプションは BSD tar にはないようだ。
普通のやり方で tar を結合するしかない。

仕様

tar ファイルの仕様は以下の URL に書いてある (POSIX.1-1988 と POSIX.1-2001 で規格化)
http://www.gnu.org/software/tar/manual/html_node/Standard.html

歴史的経緯により tar のフォーマットは大きく分けて 3 種類ある。

  • V7 Unix の tar (BSD 系のデファクトスタンダード)
  • GNU デフォルトの tar (GNU 系のデファクトスタンダード)
  • pax フォーマット (比較的新しい規格で、専用コマンド pax があったりする。 あまり使われてない )

このうち pax フォーマットについては、この記事で述べてきた通りの挙動にはならない。残念。

--ignore-zeros とは

Physically, an archive consists of a series of file entries terminated by an end-of-archive entry, which consists of two 512 blocks of zero bytes. A file entry usually describes one of the files in the archive (an archive member), and consists of a file header and the contents of the file. File headers contain file names and statistics, checksum information which tar uses to detect file corruption, and information about file types.

2 * 512 = 1024 byte を tar ファイルの終端マーカーとして置く決まりになっているようだ。
対して man tar すると出てくる --ignore-zeros の説明では

-i, --ignore-zeros
    Ignore zeroed blocks in archive.  Normally two consecutive 512-blocks filled with zeroes mean EOF and tar stops reading after  encountering them.  This option instructs it to read further and is useful when reading archives created with the -A option.

--ignore-zeros はこの終端マーカーを無視してくれるとのこと。なので cat でつなげて問題ないわけだ!

tar ファイルフォーマットのより詳しい説明が知りたいなら、先に上げた URL を読んでいけばいい。

それなら tar.gz は?

gzip 圧縮したテキストファイルは cat でつなげても大丈夫だよ
で書いた通り、 gzip は cat でそのままつなげてもちゃんと読める。

この 2 つを組み合わせて考えればわかるが、
つまり tar.gz ファイルを cat でそのままつなげても、 -i オプションさえつければちゃんと認識できてしまうのだ!
(もちろん GNU tar に限定した話)

実例

$ touch A
$ touch B
$ touch C
$ touch D
$ tar -zcf AB.tar.gz A B
$ tar -zcf CD.tar.gz C D
$ cat AB.tar.gz CD.tar.gz > ABCD.tar.gz
$ tar -iztf ABCD.tar.gz
実行結果
A
B
C
D

すごいぞ -i オプション!
もちろん tar -izxf ABCD.tar.gz とすれば、いつもどおり展開できる。

超大量に tar.gz ファイルがあるときに、覚えておいて損はなさそう。

Python でも可

Python の標準ライブラリ tarfile にも同様のオプション ignore_zeros はある。
http://docs.python.jp/3.4/library/tarfile.html

class tarfile.TarFile(name=None, mode='r', fileobj=None, format=DEFAULT_FORMAT, tarinfo=TarInfo, dereference=False, ignore_zeros=False, encoding=ENCODING, errors='surrogateescape', pax_headers=None, debug=0, errorlevel=0)

いいね!
きっと他の言語にも同様のオプションがあるんじゃないかなー。

BSD tar について

このままだと BSD tar に不公平だと思うので、 BSD tar の便利な機能も紹介したい。
BSD tar には @ という便利な記法があって、

$ tar -cf ABCD.tar @AB.tar @CD.tar

のように結合することができる。
この記法のすごいところは tar.gz ファイルであっても @AB.tar.gz のようにそのまま書いて OK
あまり使う機会はなさそうだが bz2 と gz と xz を 1 度でつなげることもできる。

免責

この情報はいかなる種類の保証も伴わずに「現状のまま」で提供するよ。
筆者はいろいろと責任を負わないし負えないよ。 (ry

5
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?