はじめに
mattnさんが以下のようなことをつぶやかれていました。
tar コマンドで z フラグを付けるとオッサンだとバレる。
— mattn (@mattn_jp) 2018年3月7日
それに対するリプへのリプ。
今は自動判定なのです。。
— mattn (@mattn_jp) 2018年3月7日
オッサンでした。
ここら辺の処理はbuffer.cのcheck_compressed_archiveという関数で行われてます。まあ今回の本題はこちらでないのでこの話はここまで。
その後もオッサン達(失礼)がオプションの話で盛り上がっていました。
さらにオッサンになると
— Hiroaki Nakamura (@hnakamur2) 2018年3月7日
tar cf - . | gzip -9 > foo.tar.gz
のように別途実行してました。
当時使ってたSunOSだかSolarisのtarはzオプションサポートしてなかった気がしますが定かではないです。
うるせぇな、tarっつったら、xvzfなんだよ。(老害
— Daisuke Maki (anovaさん) (@lestrrat) 2018年3月7日
xzf / xzvf やろ! (戦争勃発
— MURAOKA Taro (@kaoriya) 2018年3月7日
ちなみに私が展開するときは以下のように書いてます。
$ tar xfz archive.tar.gz
さて、ここまで何の疑問も持たずに読んできた人はみんなオッサンです。
オプションの指定方法
ちょっとマニュアルを見てみましょう。うーん、ウェブで見られるmanはいまいちいいのがないので御自分でman tar
してください。
さて、xzfなのかxfzなのかはともかくハイフンが付いてない指定方法の記述はありましたか?
・・・ありません。そう、実はハイフンのないオプション指定はOld Styleと言われ古い形式なのですm9(^Д^)プギャー。今どきの書き方はこうです。
$ tar -xzf archive.tar.gz
ちなみにこれができるのはGNUのtarでBSDのtarはまた違うかもしれないのですがまあLinuxでの話とします。1
ついでに、manにはありませんがinfoにはOld Styleに関する記述があります。
Old Styleを指定したときの動作
ところで、ふとOld Styleがどう処理されてるんだろうと気になりました。なお、私好みの指定方法xfzはハイフン付きで指定すると、
$ tar -xfz archive.tar.gz
tar: z: Cannot open: No such file or directory
tar: Error is not recoverable: exiting now
うんまあわかるけど、どちらかというとこっちの振る舞いの方が正しいけど、というわけで私は未だにOld Styleで書いているわけですが2それはさておき、Old Styleが指定されたときの動作です。これを見ると何故「xfz」はよくて「-xfz」は駄目なのかもわかります。
該当箇所はtar.cのdecode_options関数のここら辺
何をしているかと言うと、
- ハイフン付きじゃない指定がされてたら
- ハイフン付きのオプションにすげかえる
- その際それぞれのオプションに分離する
- 後続引数をとるタイプのオプションの場合はまとまりオプションの次の引数を挟み込む
つまり、
$ tar xfz archive.tar.gz
という指定は以下のようにオプション指定されたものとして以後の処理が行われます。
$ tar -x -f archive.tar.gz -z
一方、初めからハイフン付きの場合はこのケアは行われません。つまり、
$ tar -xfz archive.tar.gz
は以下と同様になります。3
$ tar -x -f z archive.tar.gz
zというファイルがないとファイルありませんエラーです。
あとがき
xfz派が救われたのはたまたまだったのかそういう指定をする人が実は多い(からそれを考慮した実装が行われた)のか、ハイフンありオプション形式でないtarの場合はオプション解析がどう実装されているのかなどなど謎は深まるばかりですが、昔から使われているコマンドは互換性を考慮しないといけないという苦労が表れているなと思いました。LinuxというかUNIXのコマンドソースを眺めるのは楽しいですね。