Lambdaカクテル

京都在住Webエンジニアの日記です

Invite link for Scalaわいわいランド

圧縮済みのTARファイルを展開せずにファイルを追加できる

またTARの話してる・・・

(前回のTARの話はこちら)

blog.3qe.us

GNU tar(1)のマニュアルを見ていたら、面白いことが書いてあった:

www.gnu.org

--concatenateオプション(もしくは--catenate-A)を使うことで、複数のTARアーカイブを1つに結合できるらしい。

実際に試してみると、確かにそうなった:

$ 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.txtworld.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もこの振舞いをするようだ。

blog.3qe.us

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を素朴に結合しても動かないみたい

こういう特性がある。

★記事をRTしてもらえると喜びます
Webアプリケーション開発関連の記事を投稿しています.読者になってみませんか?