2013年1月24日木曜日

リンク先のファイルを”消せない”便利なコマンド

(追記) 元記事によると、消したかったのは symlink でなくディレクトリ構造だったとのこと。。。それだとこの手も意味ないなぁ。。。

シンボリックリンクをrm -rf symlink/すると不幸になるというエントリで syuu1228 先生が何かを消し去ったらしいのですが、私はこの問題にはハマらないようにしています。参考までに何がおきたかというと、たぶんこういうこと。


hasegaw-Air:~ hasegaw$ cd work
hasegaw-Air:work hasegaw$ ln 
hasegaw-Air:work hasegaw$ mkdir a
hasegaw-Air:work hasegaw$ touch a/[abc]
hasegaw-Air:work hasegaw$ ln -s a b
hasegaw-Air:work hasegaw$ ls -l
total 8
drwxr-xr-x  3 hasegaw  staff  102 Jan 23 22:08 a
lrwxr-xr-x  1 hasegaw  staff    1 Jan 23 22:08 b -> a



hasegaw-Air:work hasegaw$ rm -rf b/ (シンボリックリンクでなく実体の a が消える)
hasegaw-Air:work hasegaw$ ls -l
total 8
lrwxr-xr-x  1 hasegaw  staff  1 Jan 23 22:08 b -> a



rm コマンドに -rf オプションを付けるから痛い目にあうのだという考え方もありますが、このオペミス対策は、単純にファイルを一つ消すことしかできない unlink コマンドを使っておくという手があります。まあファイルがひとつ消える可能性はあるのですが、意図せぬディレクトリやその中のファイルが消えることはありません。


hasegaw-Air:work hasegaw$ mkdir a
hasegaw-Air:work hasegaw$ touch a/[abc]
hasegaw-Air:work hasegaw$ ls -l
total 8
drwxr-xr-x  3 hasegaw  staff  102 Jan 23 22:09 a
lrwxr-xr-x  1 hasegaw  staff    1 Jan 23 22:08 b -> a
hasegaw-Air:work hasegaw$ unlink b/  (実体を消したいがディレクトリは知恵が足りず消せない。アヒャ)
unlink: b/: is a directory

hasegaw-Air:work hasegaw$ unlink b  (ファイルやリンクは消せる)
hasegaw-Air:work hasegaw$ ls -l
total 0
drwxr-xr-x  3 hasegaw  staff  102 Jan 23 22:09 a
hasegaw-Air:work hasegaw$




これはたとえば Linux 上で strace してみてもわかります。

[hasegaw@localhost work]$ strace unlink MY_POEM 2>&1 | grep MY_POEM
execve("/bin/unlink", ["unlink", "MY_POEM"], [/* 29 vars */]) = 0
unlink("MY_POEM")                       = -1 ENOENT (No such file or directory)write(2, "cannot unlink `MY_POEM'", 23cannot unlink `MY_POEM') = 23
[hasegaw@localhost work]$




unlink() システムコールを呼んでいるだけなので再帰処理もしてくれません。消えるとしたらファイルかシンボリックリンクぐらいです。


ちなみに同じことを rm に対してやってみると、、、アプローチが違いますね。いざという時に気が利きすぎます。

[hasegaw@localhost work]$ strace rm -rf MY_POEM 2>&1 | grep MY_POEM
execve("/bin/rm", ["rm", "-rf", "MY_POEM"], [/* 29 vars */]) = 0
newfstatat(AT_FDCWD, "MY_POEM", 0x1a79350, AT_SYMLINK_NOFOLLOW) = -1 ENOENT (No such file or directory)
unlinkat(AT_FDCWD, "MY_POEM", 0)        = -1 ENOENT (No such file or directory)
[hasegaw@localhost work]$


……と油断してたら、もっと賢い unlink がいる環境がもしあったら、私ものそのうちに洗礼を浴びることになるでしょうね、、、