at posts/single.html

シェルでワイルドカードをつかって cp するときの落とし穴

問題

例えば $HOME/tmp/conf に以下のファイルがあったとする。

$ ls $HOME/tmp/conf
other.dat  test1.conf  test2.conf

このうち、 test1.conf と test2.conf をカレントディレクトリにコピーしたい場合に、以下のコマンドを打つことがある。

cp $HOME/conf/*.conf .

でも、このコマンドはちょっと危険。 うっかり、最後のドットをつけ忘れて…

cp $HOME/conf/*.conf

としちゃうと惨事がおこる。 なぜでしょう?

答え

$ cat $HOME/tmp/conf/test2.conf
This is "test1.conf"

test2.conf が test1.conf の内容で上書きされてしまってる。 ちなみに、ディレクトリに .conf ファイルが3つ以上存在する場合は、こうはならない。

$ touch $HOME/tmp/conf/test3.conf
$ cp $HOME/tmp/conf/*.conf
cp: target `/home/machu/tmp/conf/test3.conf' is not a directory

まぁ、考えれば当たり前で、

$ cp $HOME/tmp/conf/*.conf

はシェルによって、

$ cp $HOME/tmp/conf/test1.conf $HOME/tmp/conf/test2.conf

と展開されて cp コマンドへ渡される。 なので、 test1.conf の内容が test2.conf にコピーされるという訳。

対策

打ち間違いを防ぐのは無理なので、 -i オプションを alias で付けておけばいい。

$ alias
cp='cp -i'
mv='mv -i'
rm='rm -i'

まぁ、この問題に限らず基本的なことだけど、なぜか root だけ設定されていなかったりすることもあるんだよね。

関連する日記