UNIX/Linuxの部屋 コマンド:ln


※空白区切りで AND 検索 (例:「ファイル 削除」)

コマンド ln ハードリンク・シンボリックリンクを張る。

「リンクを張る」とはファイル・ディレクトリの別名を作るようなもので、ファイル・ディレクトリを別の名前で参照することができる。リンクにはハードリンクとシンボリックリンクがあり、それぞれの利点があるが、一般的にはシンボリックリンクを使う方がよいだろう。

ハードリンクを作ることで、あるファイルの複製を作ることができるが、一度ハードリンクを作ってしまうと、参照先 (実体) や参照元などという区別はなくなってしまう。
% ln file-a file-b
とすることで、file-a と同じ内容を持つ file-b というファイルを作成することができる。これをハードリンクと言う。このとき file-a は実際に存在していなくてはならず、新たに作成される file-b が既に存在していてはいけない。一度ハードリンクを張ってしまうと、本当のファイル/別名のファイルという区別はなくなる。これは、file-a と file-b が同じ i-node を指すようになっているからである。

ハードリンクと i-node の関係について ls -li で確かめてみよう。ls に -i オプションを付けることで i-node の情報を表示することができる。
% ls -li file-a
414820 -rw-r--r-- 1 user group 10 Aug 4 14:49 file-a
現在は file-a が存在し、i-node は 414820 である。なお、i-node とは、ファイル・ディレクトリに付けられた一意な番号である。ファイル・ディレクトリ識別番号とでも考えればいいだろう。

file-a のハードリンク file-b を作成する。
% ln file-a file-b
もう一度 ls -li を実行してみよう。
% ls -li file-a file-b
414820 -rw-r--r-- 2 user group 10 Aug 4 14:49 file-a
414820 -rw-r--r-- 2 user group 10 Aug 4 14:49 file-b
file-a と file-b の i-node が同じなのに注目してほしい。i-node が同じということは、file-a と file-b は全く違いがないということである。file-a の内容を書き換えようとすると、OS は file-a の i-node が 414820 であることを調べ、ディスク中の 414820 に対応するファイルが書き換えられる。次に file-b を中身を表示しようとした場合も、OS が file-b の i-node が 414820 であることを調べ、ディスク中の 414820 に対応するファイルの中身を表示する。つまり、file-a を書き換えても file-b を書き換えても、同じディスクの領域を書き換えることになる。同様に、パーミッション、ファイルオーナーも共有される。file-a のパーミッションを変更すると file-b にも反映される。

では、削除時のことを考えてみよう。単純に削除してしまうと、file-a を削除したとき i-node 414820 に対応する領域がなくなり、file-b は残っているもののファイル自体は削除され、参照できなくなってしまう。それを避けるため、UNIX のファイルシステムはリンク数という情報を保持している。先程の ls -li の表示で、パーミッションの後の数字がそれである。file-a しか存在しないときはリンク数は 1 であるが、file-b を作成するとリンク数が 2 に増えていることに注意してほしい。file-a を削除するとき、OS はリンク数を 1 減らす。リンク数が 0 にならないとファイルの実体は削除しない。
% ls -li file-a file-b (それぞれのリンク数は2)
414820 -rw-r--r-- 2 user group 10 Aug 4 14:49 file-a
414820 -rw-r--r-- 2 user group 10 Aug 4 14:49 file-b
% rm file-a (file-aを削除)
% ls -li file-b (リンク数が1になった)
414820 -rw-r--r-- 1 user group 10 Aug 4 14:49 file-b
上の例では、rm file-a でリンク数を1減らしてもリンク数が 0 にはならないので、i-node 414820 に対応するディスク領域は削除されないわけである。この状態で rm file-b を実行すると、リンク数は 0 になり、i-node 414820 に対応するディスク領域は消去される。

なお、一般的にディレクトリのハードリンクは作成できない。これは、循環ディレクトリができないようにするためである。例えば /hoge がディレクトリの場合、
% ln /hoge /hoge/dir
を実行すると、/hoge/dir/dir/dir/dir/dir/dir/.... という無限のディレクトリができることになる (/hoge/dir は /hoge と同じだから)。そのため、ディレクトリのハードリンクは作成できないことになっている。ただし、Solaris などでは root のみがディレクトリのハードリンクを作成できる(ln コマンドでは不可能。システムコール link(2) を使う必要がある)。しかし、一般的にはシンボリックリンクを使う方がよいだろう。

ファイルシステム (df コマンドで表示されるもの) をまたいだハードリンクを作成できないことに注意。これは、ハードリンクは異なるファイルが同じ i-node を指すことで実現されているが、ファイルシステムが異なると、全く違う i-node が付けられるからである。つまり/dev/sd0 の i-node 100 が /usr/hoge だったとしても、/dev/wd0 の i-node 100 は/var/hoge かもしれない。/dev/wd0 の中のファイルと /dev/sd0 の中のファイルとでは、同じ i-node を共有することができないのである。

次に、シンボリックリンクについて説明する。ln にオプションを付けるとシンボリックリンクが作成される。
% ln -s file-a file-b
とすることで、file-a の別名である file-b ができる。シンボリックリンクはハードリンクとは違い、参照先(実体)と参照元という区別がはっきりと存在する。これは ls -l で見るとわかりやすいだろう。
% ls -l file-a file-b
-rw-r--r-- 1 user group 0 Aug 1 16:14 file-a
lrwxrwxrwx 1 user group 3 Aug 1 16:14 file-b -> file-a
先頭のファイルタイプが「l」であることから、file-b は通常ファイルではなくシンボリックリンクであり、file-a を指していることがわかる。

シンボリックリンクは、参照先が存在しなくてもエラーとならない。つまり、file-a が存在しなくても
% ln -s file-a file-b
とすることができる。また、シンボリックリンクはハードリンクとは違って、別のファイルシステムへもリンクを張ることができる。

なお、
% cd /tmp; ln -s /home/foo/bar/sample

% ln -s /home/foo/bar/sample /tmp/sample
と同じである。つまり、他のディレクトリ中のファイルへのシンボリックリンクをカレントディレクトリに作成したかったら、
% ln -s /home/foo/bar/sample
と、シンボリックリンク名を省略できる。シンボリックリンクの削除をしたいときは、普通に rm コマンドを使えばよい。rm はシンボリックリンクの指す先ではなく、リンク自体を削除する。

シンボリックリンクのパーミッション
シンボリックリンク自体のパーミッションは全く意味を持たない。
lrwxrwxrwx 1 user group 3 Aug 1 16:14 file-b -> file-a
でも
l--------- 1 user group 3 Aug 1 16:14 file-b -> file-a
でも全く違いはない。有効なのはリンク先の file-a のパーミッションである。

オプション
-f すでにリンクが張られていたら、リンクを付け替える。
% ln -s file link
% ln -s file2 link
ln: link: File exists
このようにリンクの「張り替え」のような作業をするとエラーとなるが -f オプションを付けると、この「張り替え」ができるようになる。
-s シンボリックリンクを張る。-s を付けないとハードリンクとなる。
>> FreeBSDオンラインマニュアル(man) FreeBSD ln(1)
>> Solaris10オンラインマニュアル(man) Solaris10 ln(1)
>> Linuxオンラインマニュアル(man) Linux ln(1)

読み方 ln (UNIXコマンド) [える・えぬ]

"LiNk" の略。


頑張って書いたおすすめコンテンツ!