mvコマンド の “mv: will not overwrite just-created” メッセージ
- 同じファイルが複数回のコピーを経て、複数のディレクトリに存在する( a/xxx.txt b/xxx.txt b/yyy.txt c/yyy.txt のように)
- これらのファイルを1つのディレクトリに、重複無くまとめたい( 重複しているファイルは消したい)
- ファイル名が同一なら中身も同一と仮定して良い
ここで、mv */*.txt new-dir/ と操作したら、上記メッセージに遭遇した。重複してるファイルは消えなかった。 mv -f しても状況は変わらないし、mv -uf するとメッセージはでなくなるが、(重複した)元ファイルは消えなかった。
たぶん、 mv -uf したあとに移動されていない元ファイルだけを rm すればいいんだろうけど、そもそもなんでこんなメッセージが出るんだろ? これは抑制できる動作だろうか?
左の書籍も「Classic Shell Scripting」だし。昭和のころからのUNIX使ってたら、Classicにもなるか。たのしいUNIXで覚えた世代だし(^_^;
当該メッセージを表示してるのはsrc/copy.c内の下記の部分。copy.c は mv/cpで共通に使われてる。そういえば、昔は ln/mv/cp は同一バイナリで名前が違うだけだったような気がするけど… 少なくとも4.4BSD-Liteでは別バイナリだな。NET/2も別っぽい。いつの話だ、俺が覚えてるのは(^_^; ex と vi と view はいまどきのLinuxでも同一バイナリ。
(Index of V6/usr/source/s1でも別だ。あれ???)
minixのcp.1では、「cp, mv, rm, ln, cpdir, clone」は同一バイナリだから、これと記憶がごっちゃになってるのかな、俺。BBSてだこはMinuxで動かしてたからなあ… SunOS4の /sbin はどうだったっけ?
さて、copy.c の該当部分は下記。私の遭遇した状況は、コメントに書かれているのと一緒だ。
[c]
/* Don’t let the user destroy their data, even if they try hard:
This mv command must fail (likewise for cp):
rm -rf a b c; mkdir a b c; touch a/f b/f; mv a/f b/f c
Otherwise, the contents of b/f would be lost.
In the case of `cp’, b/f would be lost if the user simulated
a move using cp and rm.
Note that it works fine if you use –backup=numbered. */
if (command_line_arg
&& x->backup_type != numbered_backups
&& seen_file (x->dest_info, dst_name, &dst_sb))
{
error (0, 0,
_("will not overwrite just-created %s with %s"),
quote_n (0, dst_name), quote_n (1, src_name));
return false;
}
[/c]
seen_file (lib/file-set.c) ではハッシュを使って、同名ファイルか否かを確認している。 !! が面白いテクニック。通常Cでは偽は0、真は0以外だけど、真値を1に固定したい場合に二重否定を使う。 __builtin_expect と組み合わせた例がboolean – Double Negation in C++ code – Stack Overflowにある。
[c]
/* Return true if there is an entry in hash table, HT,
for the file described by FILE and STATS. */
bool
seen_file (Hash_table const *ht, char const *file,
struct stat const *stats)
{
struct F_triple new_ent;
if (ht == NULL)
return false;
new_ent.name = (char *) file;
new_ent.st_ino = stats->st_ino;
new_ent.st_dev = stats->st_dev;
return !!hash_lookup (ht, &new_ent);
}
[/c]
そもそも昔のmvは、こういう確認はなかったような気がする (少なくともfileutils-3.13にはない。1996年)。root権限でmvやrmを使って痛い思いをしたことも幾度もある。そのころに比べるとUNIXのコマンドも便利に(そしておせっかいに)なったものだと思う。
リンク:
ディスカッション
コメント一覧
まだ、コメントがありません