at_yasu's blog

ロード的なことを

tarコマンド

FreeBSD7.1-PRERELEASEの事。たぶん、6系統でも同じ事が起きるかと。

tarコマンドを使うとき、「c」でtarファイルを作ります。
そのときに、「z」や「j」を付けると「gzip」や「bzip2」形式に圧縮します。
しかし、この圧縮では、極端に圧縮させたい場合などでは物足りない場合があります。
tarコマンドで作ったファイルを極端に圧縮させる場合、一度ファイルを作成してからbzip2コマンドを使うか、パイプ渡しでbzip2などに渡して「--best」を使います。
特にパイプ渡しをするとディスクリソース的に都合が良い場合があります。


FreeBSDでは、特にbadコマンドのtarでは、「f」を付けない場合はテープデバイスに出力しようとして失敗します。
「f」オプションで「/dev/stdout」を付ける事で、テープデバイスに出力しようとせず、標準出力へ書き出します*1。「A|B」とコマンドを打った場合、Aコマンドの標準出力をBの標準入力へ渡しますので、「/dev/stdout」へ書き出す事でパイプ渡しが成功します。
例えば、下記のコマンドではCapというディレクトリーを、tarコマンドでまとめ、bzip2で圧縮し、Cap.tar.bzipというファイルに書き出します。

# tar -f /dev/stdout -cv Cap | bzip2 --best -c > Cap.tar.bz2


ちなみに、MacOS10.5「Leopard」は、Gnutarを使ってますので、-fで/dev/stdoutを付けなくてもパイプ渡しは成功します。


ここの古典らへんというか、FreeBSDらしいなぁ


追記1:

ソースコード「usr.bin/tar/bsdtar.c」を読んでいたら、「/dev/tape」へ行く場合もあるみたい。__linuxっていうフラグがあるか無いかで変わるみたいだけど、Linux互換はオプションになったんでないの?

/*
 * Per POSIX.1-1988, tar defaults to reading/writing archives to/from
 * the default tape device for the system.  Pick something reasonable here.
 */
#ifdef __linux
#define _PATH_DEFTAPE "/dev/st0"
#endif

#ifndef _PATH_DEFTAPE
#define _PATH_DEFTAPE "/dev/tape"
#endif


追記2:

ソース読んでたら「O」は標準出力になりますけど、「t」の一覧表示の時のみで「c」の作成の時はできないみたいです(´・ω・`)


参考:tar,gzip,bzip2について - 試験運用中なLinux備忘録

*1:今更ながら疑問に思ったのだけど、標準出力とか入力とかってどうやって実装しているんだろう。後でソースとか古典本を読もう。