あらゆるアーカイブを管理できるツール、atool
atoolにはaunpack、apack、als、acat、adiff、arepackというコマンドがあるが、いずれもatoolのメインPerlスクリプトにリンクしており、各コマンドが持つ機能に応じてアーカイブの展開や作成などを実行する。
アーカイブを展開するaunpackは、ファイルが複数含まれている場合はファイルをサブディレクトリーに、1つだけの場合はカレント・ディレクトリーに置くが、-subdir(または-D)オプションが指定されていると、どちらの場合もサブディレクトリーに置く。この仕様はアーカイブを/tmpに展開するときに大いに役立つ。ファイルがサブディレクトリーに入っていないアーカイブをうっかり/tmpで展開して、ファイルをその中にばらまいてしまうおそれがないからだ。
atoolで扱えるtarの圧縮方式には、gzip、bzip2、compress、lzop、7z、rar、lha、ace、arj、rpm、deb、jar、7zip、cpioがあり、さらに数種の圧縮方式を扱うことができる。ただし、それぞれの圧縮方式に応じたネイティブのツールがあればの話だ。一部のアーカイブ形式については内容の一覧と展開しかできないが、これはそのアーカイブを作るプログラムが入手できないためだ。たとえば、aceアーカイブの作成や変更はできない。
それでは、いくつか使用例を見てみよう。まず、ごく簡単なファイルシステムを作り、そのtar.bz2ファイルを作成する方法を示す。もちろん、bzip2やgzipで圧縮したtarを作る方法など教わるまでもないだろう。この例を挙げたのは、これとまったく同じ構文で、どのような形式(サポートされていれば)のアーカイブでも作れることを示すためだ。
$ cd /tmp $ mkdir atest $ cd atest $ mkdir testdir $ cd testdir $ date >df1.txt $ date >df2.txt $ mkdir subdir1 $ date >subdir1/subfileb.txt $ cd /tmp/atest $ date >rawfile.txt $ apack testdir.tar.bz2 testdir testdir/ testdir/df1.txt testdir/subdir1/ testdir/subdir1/subfileb.txt testdir/df2.txt $ file testdir.tar.bz2 testdir.tar.bz2: bzip2 compressed data, block size = 900k $ tar tjvf testdir.tar.bz2 drwxrwxr-x ben/ben 0 2008-01-17 18:11 testdir/ -rw-rw-r-- ben/ben 29 2008-01-17 18:11 testdir/df1.txt drwxrwxr-x ben/ben 0 2008-01-17 18:11 testdir/subdir1/ -rw-rw-r-- ben/ben 29 2008-01-17 18:11 testdir/subdir1/subfileb.txt -rw-rw-r-- ben/ben 29 2008-01-17 18:11 testdir/df2.txt $ als testdir.tar.bz2 drwxrwxr-x ben/ben 0 2008-01-17 18:11 testdir/ -rw-rw-r-- ben/ben 29 2008-01-17 18:11 testdir/df1.txt drwxrwxr-x ben/ben 0 2008-01-17 18:11 testdir/subdir1/ -rw-rw-r-- ben/ben 29 2008-01-17 18:11 testdir/subdir1/subfileb.txt -rw-rw-r-- ben/ben 29 2008-01-17 18:11 testdir/df2.txt $ apack testdir.cpio.7z testdir 7-Zip (A) 4.51 beta Copyright (c) 1999-2007 Igor Pavlov 2007-07-25 p7zip Version 4.51 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,2 CPUs) Scanning Creating archive testdir.cpio.7z Compressing testdir/df1.txt Compressing testdir/df2.txt Compressing testdir/subdir1/subfileb.txt Everything is Ok $ als testdir.cpio.7z 7-Zip (A) 4.51 beta Copyright (c) 1999-2007 Igor Pavlov 2007-07-25 p7zip Version 4.51 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,2 CPUs) Listing archive: testdir.cpio.7z Date Time Attr Size Compressed Name ------------------- ----- ------------ ------------ ------------------------ 2008-01-17 18:11:04 ....A 29 42 testdir/df1.txt 2008-01-17 18:11:06 ....A 29 testdir/df2.txt 2008-01-17 18:11:16 ....A 29 testdir/subdir1/subfileb.txt 2008-01-17 18:11:16 D.... 0 0 testdir/subdir1 2008-01-17 18:11:11 D.... 0 0 testdir ------------------- ----- ------------ ------------ ------------------------ 87 42 3 files, 2 folders
7zip形式の場合、何も指定しなければ7zツールを使って圧縮する。しかし、ディストリビューションにp7zipパッケージが含まれているので7zの代わりに7zaをデフォルトにしたいということもあろう。その場合は、構成ファイルに次のように記述する。atoolの構成ファイルは簡単なもので、キーワードと値の対で記述する。/etc/atool.confはすべてのユーザーに、~/.atoolrcはそのユーザーに適用される。
# cat /etc/atool.conf path_7z 7za
acatを使うと、アーカイブ中のファイルを見ることができる。このコマンドラインも簡単だ。圧縮ファイルの復元ツールや展開ツールのスイッチが何だったかを思い出す必要はない。atoolは選択したファイルをstdoutに書き出す(デフォルト)。その際、展開に関するメッセージが不要な場合は、下の2番目の例に示したように、コマンドライン・オプション-qを指定する。残念な点を1つ。7zip用のツールは直接コンソールに出力できないため、ページャーを介す必要がある。デフォルトではコマンドpager
が使われるが、これはPAGER
環境変数で変更可能だ。
$ acat testdir.tar.bz2 testdir/df1.txt testdir/df1.txt Thu Jan 17 18:11:04 EST 2008 $ acat -q testdir.tar.bz2 testdir/df1.txt Thu Jan 17 18:11:04 EST 2008 $ export PAGER=less $ acat -q -p testdir.cpio.7z testdir/df1.txt 7-Zip (A) 4.51 beta Copyright (c) 1999-2007 Igor Pavlov 2007-07-25 p7zip Version 4.51 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,2 CPUs) Processing archive: testdir.cpio.7z Extracting testdir/df1.txt Everything is Ok Thu Jan 17 18:11:04 EST 2008 $ acat -p testdir.cpio.7z testdir/df1.txt 2>/dev/null Thu Jan 17 18:11:04 EST 2008
次に、アーカイブを展開する例を見てみよう。これは、atoolの十八番だ。すでに述べたように、atoolを使う限り、アーカイブがファイルをサブディレクトリーの中に展開してくれるかどうかをいちいち確認する必要がない。次に示すのは、先の例で作成したcpioファイルを展開する例だ。この場合、ファイルは元々サブディレクトリーの中にあるため、取り立ててatoolのありがたみはない。そこで、アーカイブのルート・ディレクトリーにファイルを2つ含むjarアーカイブを作り、これをaunpackを使って展開した。これが、下の2番目の例だ。2つのファイルは、確かにサブディレクトリーの中に置かれている。
$ cd /tmp/atest $ mkdir extraction $ cd extraction $ aunpack ../testdir.cpio.7z ... Processing archive: ../testdir.cpio.7z Extracting testdir/df1.txt Extracting testdir/df2.txt Extracting testdir/subdir1/subfileb.txt Extracting testdir/subdir1 Extracting testdir Everything is Ok testdir.cpio.7z: extracted to `testdir' [ben@alkid extraction]$ ls -lh total 8.0K drwxrwxr-x 3 ben ben 4.0K Thu.17.Jan 18:01 testdir/ $ cat ./testdir/df2.txt Thu Jan 17 18:11:06 EST 2008 $ cd /tmp/atest/testdir [ben@alkid testdir]$ ls -l total 24 -rw-rw-r-- 1 ben ben 29 2008-01-17 18:11 df1.txt -rw-rw-r-- 1 ben ben 29 2008-01-17 18:11 df2.txt drwxrwxr-x 2 ben ben 4096 2008-01-17 18:11 subdir1 $ apack ../nasty-archive.jar df1.txt df2.txt adding: df1.txt (stored 0%) adding: df2.txt (stored 0%) $ cd .. $ rm -rf extraction $ cd extraction $ aunpack ../nasty-archive.jar Archive: ../nasty-archive.jar extracting: Unpack-3078/df1.txt extracting: Unpack-3078/df2.txt nasty-archive.jar: extracted to `nasty-archive' (multiple files in root) $ ls -lR .: total 8 drwx------ 2 ben ben 4096 2008-01-17 18:40 nasty-archive ./nasty-archive: total 16 -rw-rw-r-- 1 ben ben 29 2008-01-17 18:11 df1.txt -rw-rw-r-- 1 ben ben 29 2008-01-17 18:11 df2.txt
この例を見て誰しも思うのが、アーカイブを展開するときに作成されるサブディレクトリーに自動的に移ってほしいということ。残念ながら、それにはaunpackをシェル関数で包む必要がある。次に示すシェル関数は、atoolマニュアル・ページにあるものを基に、サブプロセスの実行と、デフォルトで-iを含むようにエイリアスされているrmコマンドを回避するように修正してある。
aunpack () { TMP=$(mktemp /tmp/aunpack.XXXXXXXXXX); atool -x --save-outdir=$TMP "$@" DIR="$(cat $TMP)" [ "$DIR" != "" -a -d "$DIR" ] && cd "$DIR" /bin/rm -f $TMP }
arepackとadiffは、アーカイブのまま扱うコマンドだ。arepackはアーカイブの形式を変更し、adiffは2つのアーカイブを比較してそのdiffを表示する。args_diffオプションはdiffを生成する際のオプションで、デフォルトは-ruだ。次に示す例では、先の例で使ったtestdirを利用してテストしている。最後の例は、diffコマンドライン・オプションのデフォルトを変更し、diffで追加されたものだけが表示されるようにしている。
$ ls -l testdir -rw-rw-r-- 1 ben ben 29 2008-01-17 18:11 df1.txt -rw-rw-r-- 1 ben ben 29 2008-01-17 18:11 df2.txt drwxrwxr-x 2 ben ben 4096 2008-01-17 18:11 subdir1 $ ls -l testdir/subdir1/ -rw-rw-r-- 1 ben ben 29 2008-01-17 18:11 subfileb.txt $ apack testdir-first.tar.gz testdir testdir/ testdir/df1.txt testdir/subdir1/ testdir/subdir1/subfileb.txt testdir/df2.txt $ mv testdir/df2.txt testdir/subdir1/ $ date >>testdir/subdir1/subfileb.txt $ date >testdir/newfileA.txt $ apack testdir-second.tar.gz testdir testdir/ testdir/newfileA.txt testdir/df1.txt testdir/subdir1/ testdir/subdir1/subfileb.txt testdir/subdir1/df2.txt $ adiff testdir-first.tar.gz testdir-second.tar.gz Only in Unpack-1710/testdir: df2.txt Only in Unpack-7823/testdir: newfileA.txt Only in Unpack-7823/testdir/subdir1: df2.txt diff -ru Unpack-1710/testdir/subdir1/subfileb.txt Unpack-7823/testdir/subdir1/subfileb.t xt --- Unpack-1710/testdir/subdir1/subfileb.txt 2008-01-17 18:11:16.000000000 +1000 +++ Unpack-7823/testdir/subdir1/subfileb.txt 2008-01-17 22:39:40.000000000 +1000 @@ -1 +1,2 @@ Thu Jan 17 18:11:16 EST 2008 +Thu Jan 17 22:39:40 EST 2008 $ vi ~/.atoolrc args_diff -Nuar $ adiff testdir-first.tar.gz testdir-second.tar.gz |grep ^+ +++ Unpack-9186/testdir/df2.txt 1970-01-01 10:00:00.000000000 +1000 +++ Unpack-9186/testdir/newfileA.txt 2008-01-17 22:39:48.000000000 +1000 +Thu Jan 17 22:39:48 EST 2008 +++ Unpack-9186/testdir/subdir1/df2.txt 2008-01-17 18:11:06.000000000 +1000 +Thu Jan 17 18:11:06 EST 2008 +++ Unpack-9186/testdir/subdir1/subfileb.txt 2008-01-17 22:39:40.000000000 +1000 +Thu Jan 17 22:39:40 EST 2008
以上のように、ネイティブのコマンドが異なる圧縮方式やアーカイブ形式でも、atoolを使えば同じコマンドで操作することができる。
Ben Martin 10年以上にわたってファイルシステムを研究。博士課程を修了し、現在、libferris、ファイルシステム、検索ソリューションを中心にコンサルティングをしている。