/hoge/huga
内のfile
で始まるファイルをアーカイブ化し
/hoge/output.tar
に出力する~といった場合に、
以下のようなコマンドを使ったところ困ったことになったのでめも
# これは誤りのコマンドなのでこの様式で実行するとひどいことになる。こうかいしませんね?
$ tar cvf /hoge/huga/file* /hoge/output.tar
tarコマンドのつかいかた
tarコマンドでアーカイブを作成する際には大体以下の様式でコマンドを実行する。
$ tar cvf <出力ファイル名> <アーカイブ対象ファイル ...>
で、冒頭の例示のように「このディレクトリ配下全部アーカイブしたいなぁ...」
と思って以下のように組み立てたとする。
$ tar cvf /hoge/output.tar /hoge/huga/file*
...まぁ/hoge/output.tar
に理想通り出来上がる。
シェルコマンドでの「*(ワイルドカード)」
ところで、シェルコマンドにおける「*(ワイルドカード)」の扱いを振り返ってみよう。
$ ls /hoge/huga/
data1.txt data2.txt file1.txt file2.txt file3.txt
ファイルがこのようになっていた場合に以下のコマンドを入れてみる。
$ ls /hoge/huga/file*
file1.txt file2.txt file3.txt
なぜこのようになるか。
シェルはワイルドカードを含むパスを自動的に展開する。
例えば、/hoge/huga/file*
は、/hoge/huga
ディレクトリ内の
file
で始まるすべてのファイルパスを列挙する。
つまり以下のように入力されたものとして解釈する。
$ ls /hoge/huga/file1.txt /hoge/huga/file2.txt /hoge/huga/file3.txt
lsコマンドは引数に含まれているファイルの情報を出力するので
いくら指定されても問題ないってワケ。
試しに以下のコマンドで出力される内容を確認するとわかりやすい。
$ echo ~/*
ホームディレクトリに格納されているディレクトリ、ファイルが
先に示した例のように列挙される。
tarコマンドの指定順序を変えてみる
ここからが本題。先ほど組み立てたコマンドをもう一度。
$ tar cvf /hoge/output.tar /hoge/huga/file*
このファイル指定順序を反転して考えてみる。
$ tar cvf /hoge/huga/file* /hoge/output.tar
このコマンドを受け取ったシェルは、ワイルドカードを展開し以下のように解釈する。
$ tar cvf /hoge/huga/file1.txt /hoge/huga/file2.txt /hoge/huga/file3.txt /hoge/output.tar
まるで/hoge/huga/file1.txt
を出力先として実行しているようになってしまう。
これを実行すると以下のように処理を進めていく。
-
/hoge/huga/file1.txt
に/hoge/huga/file2.txt
をアーカイブとして書き込む。 -
/hoge/huga/file1.txt
に/hoge/huga/file3.txt
を追加で書き込む。 -
/hoge/huga/file1.txt
に/hoge/output.tar
を追加で書き込もうとするが、
大体の場合当該ファイルは存在しないためエラーになる。 - 前述のエラーによってコマンドが停止する。
実行結果としては/hoge/huga/file2.txt
、/hoge/huga/file3.txt
が書き込まれた
かつての面影はない/hoge/huga/file1.txt
が出来上がってしまう。
当然ながら/hoge/huga/file1.txt
の内容はロストする上、/hoge/output.tar
は作成されない。
さいごに
他のcp
コマンドやmv
コマンドなどと同じように「ここからここに(A→B)」のような書き方もあれば、
今回のtar
コマンドのように「ここに、これらを(A←B[])」のような書き方(※追記あり)もあるので、
元データ、宛先など、それぞれのコマンドが必要としている情報を理解して利用していきたいものです。
2024/11/09追記
tarコマンドは-f
オプションの引数を出力対象にするので、
以下のようにオプションの引数ですよと明示的にしておくと
間違いは減るかもしれません。
※@shibapさんありがとうございます!
$ tar cv -f /hoge/output.tar /hoge/huga/file*
オプションはまとめて記載できてしまうので、
慣れてきた頃にまとめて打ち込むクセがついて
メモや手順書にそのまま書いてしまう事はあるかもしれません。
それを見た「そのコマンドをなんとなく使っている人」が他のコマンドと
同じノリで使うことでこのような過ちをする可能性はあるので、
記載者は「気をつけるオプションは分離するように」、
打鍵者は「分離されている意図、そのオプションの働き」を
押さえておくと良いのかなと思います。
参考