あらゆるアーカイブを管理できるツール、atool

  atool を利用すると、さまざま方式で圧縮された、さまざまな形式のアーカイブを同じコマンドライン・インタフェースで扱うことができる。実体はPerlスクリプトのコレクションで、実際の処理はそれぞれに該当するネイティブのツールが行う。アーカイブを展開するコマンドやオプションはアーカイブの形式ごとに異なるが、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、ファイルシステム、検索ソリューションを中心にコンサルティングをしている。

Linux.com 原文