home ホーム search 検索 -  login ログイン  | reload edit datainfo version cmd icon diff delete  | help ヘルプ

技術/UNIX/cpio

技術/UNIX/cpio

技術 / UNIX / cpio
id: 491 所有者: msakamoto-sf    作成日: 2009-11-19 18:30:07
カテゴリ: Linux UNIX シェルスクリプト 

RPMパッケージやAppleの"pax"インストーラ, Linux kernel 2.6でのinitramfsに使われていたりと、何気なく現役で使われている。
というわけで、例によって自分用メモ。

基本的な使い方

GNU cpio HTML ドキュメントにもTutorialが用意されており、基本は「Copy-out:アーカイブ作成」「Copy-in:アーカイブ展開」「Copy-pass:ディレクトリ単位でコピー」の3つのモードを使い分ける。

Copy-out : アーカイブ作成

cpio {-o|--create} その他オプション < 対象ファイル一覧 > アーカイブファイル

標準入力でファイル名の一覧を与えると、標準出力にアーカイブデータを出力する。findコマンドを組み合わせると使いやすくなる。

$ find . -print | cpio -ov > foo.cpio

パイプでつなげれば、gzip圧縮もできる。拡張子としては".cpio.gz"や".cpgz"が使われるようだ。

$ find . -print | cpio -o | gzip > foo.cpio.gz

Copy-in : アーカイブ展開

cpio {-i|--extract} その他オプション < アーカイブファイル

標準入力でアーカイブデータを与えると、アーカイブの展開を行う。

$ cpio -iv < foo.cpio

"-t"オプションを指定すると、実際の展開は行わず入力ファイル名の一覧を表示するだけとなる。

$ cpio -t < foo.cpio

Copy-pass : ディレクトリ単位でコピー

cpio {-p|--pass-through} その他オプション コピー先ディレクトリ名 < 対象ファイル一覧

例:

$ cd <src_dir>
$ find . -print | cpio -pvd <dest_dir>

"-d"オプションをつけておくと、"<dest_dir>"が存在しない場合は自動的に作成してくれる。

その他

改行を含むファイル名

ファイル名に改行を含むファイルをアーカイブしたい場合は、"-0"または"--null"で、ファイル名の一覧がNULL区切りであることを指示しておく。
同時に、findコマンドでファイル名をNULL区切りにするよう"-print0"を使う。

$ find . -print0 | cpio -ov0 > foo.cpio
$ find . -print0 | cpio --null -ov > foo.cpio

findコマンドと組み合わせる時の、findの"-depth"オプション

GNU cpio HTMLドキュメントのTutorialを読んでいたら、findコマンドに"-depth"オプションをつけた例がある。

find . -print -depth | cpio -ov > tree.cpio

これについて実際に実験してみて、「何故 "-depth" 付を推奨しているのか」分かったのでメモ。ちなみにCentOS 5.2 の GNU find 4.2.27 を使うと、"-print -depth"の順にするとwarningが出てしまったので、以降は"-depth -print"の順にしている。

まず、"-depth"オプション(or "-d")を指定すると「ディレクトリ階層が深い方を優先して処理する」ようになる。
例:

$ cd cpio_test/
$ find .
.
./foo
./foo/bar
./foo/bar/test3.txt
./foo/test2.txt
./test1.txt
$ find . -depth
./foo/bar/test3.txt
./foo/bar
./foo/test2.txt
./foo
./test1.txt
.

これとcpioを組み合わせ、展開した時の動作を考えてみる。

  • "-depth"無し:先にディレクトリを作成し、権限を復元し、次にディレクトリの中のエントリを展開していく。
  • "-depth"有り:まずディレクトリ中のエントリを展開し、最後にディレクトリの権限を復元する。

このため、"-depth"有りで作成されたcpioアーカイブを展開する時は

cpio -i < foo.cpio

ではなくて、"-d"でディレクトリの自動作成を有効にした上で展開する必要がある。

cpio -id < foo.cpio

もし"-d"を使わない場合は、予めディレクトリだけは作成しておく必要がある。

わざわざ"-depth"有りの動作を使う理由は、ディレクトリの権限が特殊な場合を想定しているからである。
一番分かりやすい例だと、そのディレクトリ権限の所有者bitから"w"が落ちている場合である。

$ cd cpio_test/
$ find . | xargs ls -ld
drwxrwxr-x 3 msakamoto msakamoto 4096 11月 18 19:07 .
drwxrwxr-x 3 msakamoto msakamoto 4096 11月 18 19:09 ./foo
dr-x------ 2 msakamoto msakamoto 4096 11月 18 19:14 ./foo/bar
  ^ "test3.txt"を作成後に、chmod u-w して"w"権限を落としている。
-rw-rw-r-- 1 msakamoto msakamoto   10 11月 18 19:14 ./foo/bar/test3.txt
-rw-rw-r-- 1 msakamoto msakamoto    6 11月 18 19:08 ./foo/test2.txt
-rw-rw-r-- 1 msakamoto msakamoto    6 11月 18 19:08 ./test1.txt

この場合に、"-depth"無しでアーカイブしたcpioを展開すると、"foo/bar/test3.txt"が展開できなくなる。

  1. "./foo/bar" ディレクトリを作成+権限を復元 → ownerの"w"フラグが落ちる。
  2. "./foo/bar/test3.txt" ファイルを作成しようとするが、ディレクトリの"w"フラグが落ちているので書き込めない。

実際にやってみる:

$ cd cpio_test/
$ find . -print | cpio -o > ../test1.cpio
$ cd ..; mkdir test1; cd test1
$ cpio -iv < ../test1.cpio
.
foo
foo/bar
cpio: foo/bar/test3.txt: 許可がありません
foo/bar/test3.txt
foo/test2.txt
test1.txt
1 block

こういう場合に "-depth"有りでアーカイブしておけば、中のファイルツリーを展開した後で権限を復元するようになるので、問題は発生しなくなる。
実際にやってみる:

$ cd cpio_test/
$ find . -depth -print | cpio -o > ../test2.cpio
$ cd ..; mkdir test2; cd test2
$ cpio -ivd < ../test2.cpio  # ← "-d"オプションを忘れずに!
foo/bar/test3.txt
foo/bar
foo/test2.txt
foo
test1.txt
.
1 block


プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2009-11-20 17:17:49
md5:2863537e337c35da88c7384e47b0c205
sha1:3e1dc8abe164ca9f0f95d6a5a3434807891e3207
コメント
コメントを投稿するにはログインして下さい。