またTARの話してる・・・
(前回のTARの話はこちら)
GNU tar(1)のマニュアルを見ていたら、面白いことが書いてあった:
--concatenate
オプション(もしくは--catenate
、 -A
)を使うことで、複数のTARアーカイブを1つに結合できるらしい。
- GZIPやZstandardなどの一般的な圧縮形式は、結合してから圧縮しても圧縮してから結合しても等価になる
- TARをcatで結合しても展開できる
- 圧縮したTARアーカイブを結合するとファイルを追加できる
- cpio形式
実際に試してみると、確かにそうなった:
$ echo first file > first.txt $ echo another file > second.txt $ tar cf first.tar first.txt $ tar cf second.tar second.txt # -Aで破壊的に結合する -- 最初に指定したファイルは結合後のファイルで置換される $ tar Af first.tar second.tar $ tar --list --file first.tar first.txt second.txt
これは、単純にファイルを結合しているのではなく、きちんとヘッダを結合しているので、Validな1つのTARアーカイブが生成される。ただし、破壊的にTARアーカイブが結合されることに注意しなければならない(この例では、first.tar
は結合後のTARで置換されてしまった)。
GZIPやZstandardなどの一般的な圧縮形式は、結合してから圧縮しても圧縮してから結合しても等価になる
ところで、あまり知られていないのだが、GZIP形式は以下のような特性を満たす:
- 🗜️(📦1) + 🗜️(📦2) = 🗜️(📦1 + 📦2)
- ここで、🗜️はgzip圧縮することを表す
- 📦1,📦2はそれぞれデータ
- +は単純にファイルを結合することを表す
hello.txt
とworld.txt
とで試してみよう:
$ echo "hello" > hello.txt $ echo "world" > world.txt $ cat hello.txt world.txt hello world $ gzip -k hello.txt $ gzip -k world.txt $ cat hello.txt.gz world.txt.gz > helloworld.txt.gz $ zcat helloworld.txt.gz hello world
結合してからGZIP圧縮しても、GZIP圧縮してから結合しても同じ結果が得られた。これは面白い。
ちなみに、多くの圧縮形式はこの要件を満たしている:
$ xz -k hello.txt $ xz -k world.txt $ cat hello.txt.xz world.txt.xz > helloworld.txt.xz $ xz -d helloworld.txt.xz $ cat helloworld.txt hello world
他にも、先日紹介したZStandardもこの振舞いをするようだ。
TARをcatで結合しても展開できる
さらに面白いことに、なんとGNU tar(1)はcat
で素朴に結合したTARファイルを展開できる。ただし、TAR形式としてはinvalidなので、-i
/ --ignore-zeros
オプションが必要になる。
$ tar cf hello.tar hello.txt $ tar cf world.tar world.txt $ cat hello.tar world.tar > helloworld.tar $ tar --list -if helloworld.tar hello.txt world.txt $ tar ixvf helloworld.tar hello.txt world.txt
-i
しなければならないのは、cat
で結合してもぴったりくっつくわけではなく、ブロック単位でくっつくことになりNULLでパディングされるためである。
圧縮したTARアーカイブを結合するとファイルを追加できる
この2つのテクニックを組み合わせると、圧縮済みのTARファイル同士をくっつけることで、アーカイブを展開せずにアーカイブにファイルを追加できる。
$ zstd hello.tar $ zstd world.tar $ cat hello.tar.zst world.tar.zst > combined.tar.zst $ tar axivf combined.tar.zst hello.txt world.txt
ただもちろん、このテクニックはイレギュラーなもの。
cpio形式
ところで、TARの親戚のCPIOという形式がある。
- TARは(テープでの動作効率のために)先頭にヘッダ領域があるが、CPIOはファイル全体に散らばっているので部分的な破損に強い
- CPIOを素朴に結合しても動かないみたい
こういう特性がある。