lnコマンドおさらい

宣言通り、LinuCの勉強中です。シンボリックリンクとハードリンクの挙動、毎回忘れてググってしまうので書き留めておく。 特に削除する時の挙動が曖昧になるので動作検証してちゃんと覚えたい。

シンボリックリンクとハードリンク

シンボリックリンクとハードリンクの違いの前に、Linuxにおけるファイルとは何かをおさらい。Linuxでは、ファイルをディスクに保存すると、ユニークなiノード番号が割り振られる。(ちなみにディレクトリも特殊な形のファイルである。)このiノードには、ファイルに関する様々な情報が保持されている。

例えば、ファイルのアクセス権やファイルサイズ、ファイル種別などのls -lで閲覧できる情報などと、ディスク上の物理的な保存場所を示す情報などである。 物理的な保存場所に格納されているデータがファイルの実体であり、たとえ実体がひとつであってもその実体を参照するファイルが複数存在する、ということはありえる。これがハードリンク。

ハードリンクの場合は、元のファイルとハードリンクとして作成したファイルのどちらも同じiノードを持っていてファイルの実体がひとつ(つまり物理的な保存場所が同一)なので、この二つに区別はない。いずれかを編集すると当然両方に影響がある。 同一の実体ファイルに対して変更を加えているからである。ハードリンクが3つ、4つ、と増えても同じである。iノードはファイルシステムごとに管理されるため、ハードリンクはリンク元のファイルが存在する同一のファイルシステム上にしか作成できない。下記の例だと、file.originalが存在するファイルシステム上だけでこれをリンク元にしたハードコピーが作成できる。

シンボリックリンクは参照先のファイルの場所(実体ファイルの場所ではない)を示すファイル。いわゆるMacのエイリアス、Winでいうショートカット。シンボリックリンクを削除してもファイルの実体には影響がないし、逆にシンボリックリンクが残ったまま実体ファイルを削除することも可能。(ただしリンクはエラーとなる。)シンボリックリンクが保持している情報は、参照先のファイルのパスになるので別のファイルシステム上からリンクを作成することができる。

ハードリンクについて

ハードリンク作成時のコマンドはln リンク元(=実体) リンクファイル

ハードリンクの挙動

ハードリンクはiノードが全て同じ。また、左から3番目の数字は参照の数を表すので、ハードリンクが増えるたびに数値が増えていることがわかる。

 1~ ❯❯❯ touch file.original
 2~ ❯❯❯ ln file.original file.hard1
 3~ ❯❯❯ ls -il file*
 470677112 -rw-r--r--  2 mochiko  2033490572  0  9 19 00:11 file.hard1
 570677112 -rw-r--r--  2 mochiko  2033490572  0  9 19 00:11 file.original
 6~ ❯❯❯ ln file.hard1 file.hard2
 7~ ❯❯❯ ls -il file*
 870677112 -rw-r--r--  3 mochiko  2033490572  0  9 19 00:11 file.hard1
 970677112 -rw-r--r--  3 mochiko  2033490572  0  9 19 00:11 file.hard2
1070677112 -rw-r--r--  3 mochiko  2033490572  0  9 19 00:11 file.original
11~ ❯❯❯

コピーするとiノードは異なるものになるので編集してもお互い影響を受けない。

 1~ ❯❯❯ cp -pi file.hard1 file.hard-copy
 2~ ❯❯❯ ls -il file*
 370677358 -rw-r--r--  1 mochiko  2033490572  0  9 19 00:11 file.hard-copy
 470677112 -rw-r--r--  3 mochiko  2033490572  0  9 19 00:11 file.hard1
 570677112 -rw-r--r--  3 mochiko  2033490572  0  9 19 00:11 file.hard2
 670677112 -rw-r--r--  3 mochiko  2033490572  0  9 19 00:11 file.original
 7~ ❯❯❯
 8~ ❯❯❯ echo "Hello Linux" > file.original
 9~ ❯❯❯ cat file.original
10Hello Linux
11~ ❯❯❯ cat file.hard1
12Hello Linux
13~ ❯❯❯ cat file.hard2
14Hello Linux
15~ ❯❯❯ cat file.hard-copy
16~ ❯❯❯

ハードリンクの削除

rm ハードリンク or unlink ハードリンクでハードリンクの削除が可能。

 1~ ❯❯❯ ls -li file.original file.hard*
 270677358 -rw-r--r--  1 mochiko  2033490572   0  9 19 00:11 file.hard-copy
 370677112 -rw-r--r--  3 mochiko  2033490572  12  9 19 00:49 file.hard1
 470677112 -rw-r--r--  3 mochiko  2033490572  12  9 19 00:49 file.hard2
 570677112 -rw-r--r--  3 mochiko  2033490572  12  9 19 00:49 file.hard3
 670677112 -rw-r--r--  3 mochiko  2033490572  12  9 19 00:49 file.original
 7~ ❯❯❯
 8~ ❯❯❯ rm file.hard1
 9~ ❯❯❯ ls -li file.original file.hard*
1070677358 -rw-r--r--  1 mochiko  2033490572   0  9 19 00:11 file.hard-copy
1170677112 -rw-r--r--  3 mochiko  2033490572  12  9 19 00:49 file.hard2
1270677112 -rw-r--r--  3 mochiko  2033490572  12  9 19 00:49 file.hard3
1370677112 -rw-r--r--  3 mochiko  2033490572  12  9 19 00:49 file.original
14~ ❯❯❯
15~ ❯❯❯ unlink file.hard3
16~ ❯❯❯ ls -li file.original file.hard*
1770677358 -rw-r--r--  1 mochiko  2033490572   0  9 19 00:11 file.hard-copy
1870677112 -rw-r--r--  2 mochiko  2033490572  12  9 19 00:49 file.hard2
1970677112 -rw-r--r--  2 mochiko  2033490572  12  9 19 00:49 file.original
20~ ❯❯❯

ハードリンクが削除されてもそのファイルへの参照が残っていればファイルの実体が消えることはない。なので、もともとハードリンクの参照元となっていたfile.originalを先に削除しても他のハードリンクには影響がない。

1~ ❯❯❯ ls -li file.*
270677112 -rw-r--r--  2 mochiko  2033490572  12  9 19 00:49 file.hard
370677112 -rw-r--r--  2 mochiko  2033490572  12  9 19 00:49 file.original
4~ ❯❯❯ unlink file.original
5~ ❯❯❯ ls -li file.*
670677112 -rw-r--r--  1 mochiko  2033490572  12  9 19 00:49 file.hard
7~ ❯❯❯

シンボリックリンクについて

シンボリックリンク作成時のコマンドはln -s リンク元(=実体) リンクファイル

シンボリックリンクの挙動

ls -lで確認するとファイル種別はシンボリックリンクを表すlとなり、リンク元のファイル名も取得できている。ハードリンクに対してシンボリックリンクを作成することも可能。

 1~ ❯❯❯ ln -s file.original file.symlink
 2~ ❯❯❯ ls -il file.original file.sym*
 370677112 -rw-r--r--  3 mochiko  2033490572   0  9 19 00:11 file.original
 470679436 lrwxr-xr-x  1 mochiko  2033490572  13  9 19 00:31 file.symlink@ -> file.original
 5~ ❯❯❯
 6~ ❯❯❯ ln -s file.hard2 file.symlink2
 7~ ❯❯❯ ls -il file*
 870677358 -rw-r--r--  1 mochiko  2033490572   0  9 19 00:11 file.hard-copy
 970677112 -rw-r--r--  3 mochiko  2033490572  12  9 19 00:35 file.hard1
1070677112 -rw-r--r--  3 mochiko  2033490572  12  9 19 00:35 file.hard2
1170677112 -rw-r--r--  3 mochiko  2033490572  12  9 19 00:35 file.original
1270679436 lrwxr-xr-x  1 mochiko  2033490572  13  9 19 00:31 file.symlink@ -> file.original
1370679720 lrwxr-xr-x  1 mochiko  2033490572  10  9 19 00:39 file.symlink2@ -> file.hard2
14~ ❯❯❯

シンボリックリンクのコピーには、オプションの-dが必要。オプションを付けないでコピーすると、リンク元のファイルの中身をファイルとしてコピーしてしまう。file.symlink-copyのファイル種別がリンクではなく通常ファイルになっているのがわかる。

1~ ❯❯❯ cp file.symlink file.symlink-copy
2~ ❯❯❯ ls -il file.sym*
370679436 lrwxr-xr-x  1 mochiko  2033490572  13  9 19 00:31 file.symlink@ -> file.original
470679879 -rw-r--r--  1 mochiko  2033490572  12  9 19 00:42 file.symlink-copy
570679720 lrwxr-xr-x  1 mochiko  2033490572  10  9 19 00:39 file.symlink2@ -> file.hard2
6~ ❯❯❯

次の例のふたつは一見同じに見えるが、上段はシンボリックリンクのリンク元であるfile.originalをcatしたもので、下段は先ほどの-dなしのシンボリックリンクのコピーによってfile.originalの内容がfile.symlink-copyのファイルに書き込まれたものをcatしている。リンク元のデータが書き換わっても完全に別のファイルとして存在しているfile.symlink-copyは影響を受けない。

 1~ ❯❯❯ cat file.symlink
 2Hello Linux
 3~ ❯❯❯ cat file.symlink-copy
 4Hello Linux
 5~ ❯❯❯
 6~ ❯❯❯ echo "Hello World" > file.original
 7~ ❯❯❯ cat file.symlink
 8Hello World
 9~ ❯❯❯ cat file.symlink-copy
10Hello Linux
11~ ❯❯❯

シンボリックリンクの削除

rm シンボリックリンク or unlink シンボリックリンクで削除が可能。シンボリックリンクを単純に削除したい場合はunlinkコマンドを利用する方が安全。 rmコマンドを使う際はrm file.symlink/とスラッシュを付けて実行するとリンクの参照先のファイル自体が削除されてしまうので注意が必要である。

 1~ ❯❯❯ rm file.symlink
 2~ ❯❯❯ ls -li file.original file.sym*
 370677112 -rw-r--r--  2 mochiko  2033490572  12  9 19 00:49 file.original
 470679879 -rw-r--r--  1 mochiko  2033490572  12  9 19 00:42 file.symlink-copy
 570679720 lrwxr-xr-x  1 mochiko  2033490572  10  9 19 00:39 file.symlink2@ -> file.hard2
 670681303 lrwxr-xr-x  1 mochiko  2033490572  13  9 19 01:00 file.symlink3@ -> file.original
 7~ ❯❯❯
 8~ ❯❯❯ unlink file.symlink3
 9~ ❯❯❯ ls -li file.original file.sym*
1070677112 -rw-r--r--  2 mochiko  2033490572  12  9 19 00:49 file.original
1170679879 -rw-r--r--  1 mochiko  2033490572  12  9 19 00:42 file.symlink-copy
1270679720 lrwxr-xr-x  1 mochiko  2033490572  10  9 19 00:39 file.symlink2@ -> file.hard2
13~ ❯❯❯

スラッシュをつけて実行するとリンク元のファイルfile.hard2自体が削除されている。その結果、file.symlink2は参照する先がなくてエラーを生じる。

 1~ ❯❯❯ ls -li file.*
 270677358 -rw-r--r--  1 mochiko  2033490572   0  9 19 00:11 file.hard-copy
 370677112 -rw-r--r--  2 mochiko  2033490572  12  9 19 00:49 file.hard2
 470677112 -rw-r--r--  2 mochiko  2033490572  12  9 19 00:49 file.original
 570679879 -rw-r--r--  1 mochiko  2033490572  12  9 19 00:42 file.symlink-copy
 670679720 lrwxr-xr-x  1 mochiko  2033490572  10  9 19 00:39 file.symlink2@ -> file.hard2
 7~ ❯❯❯
 8~ ❯❯❯ rm file.symlink2/
 9~ ❯❯❯ ls -li file.*
1070677358 -rw-r--r--  1 mochiko  2033490572   0  9 19 00:11 file.hard-copy
1170677112 -rw-r--r--  1 mochiko  2033490572  12  9 19 00:49 file.original
1270679879 -rw-r--r--  1 mochiko  2033490572  12  9 19 00:42 file.symlink-copy
1370679720 lrwxr-xr-x  1 mochiko  2033490572  10  9 19 00:39 file.symlink2@ -> file.hard2
14~ ❯❯❯ cat file.symlink2
15cat: file.symlink2: No such file or directory
16~ ❯❯❯

蛇足。上記のようなまとめを書いていて、途中で「リンク元」と「リンク先」がどっちがどっちか分からなくなった。個人的にオリジナルの方を「リンク元」と呼ぶのに違和感を感じてしまう。参照される先のファイル、というのと混ざるためかもしれない。他の人のブログなどで誤用されていたこともあり、ますますあやふやになって調べたら、同じようなことを書いている人がいて、私だけではなかったのだなと妙な安心を抱いた。

シンボリックリンクの「リンク元」と「リンク先」

とにかく「リンク元」が「オリジナル」だって思うことにします。

私もこれで行こうと思います。