ファイルシステムと書庫

INPUT · スライド

同じ中身に2つめの名前(`ln`)

01 / 08

ファイルの正体は「名前」ではない

ここまで、ファイルとは「名前が付いた中身」だと思ってきたよね。実はもう少し細かく分かれているんだ。

名前(memo.txt)  ↓ 指している中身の管理票(inode)  ↓ 指している実際のデータ

真ん中の inode(アイノード)が主役だよ。番号が振られていて、そこに大きさ・権限・持ち主・データの置き場所が書いてある。

名前は inode を指す札にすぎないんだ。

~ $ ls -li moto.txt      4 -rw-r--r--  1 manabiya manabiya  6  moto.txt   inode 番号

ls -i で番号が見られるよ。stat -c %i でも読めるね。

そして札は、1つの inode に何枚でも付けられるんだ。それがハードリンクだよ。

02 / 08

-s を付けなければハードリンク

作り方は前の回とほとんど同じで、-s付けないだけだよ。

~ $ ln moto.txt kata.txt~ $ stat -c '%i %h' moto.txt kata.txt4 24 2

2つの数を見てね。

%i  inode 番号   → どちらも 4(同じ中身!)%h  名前の数     → 2(札が2枚)

ls -l の左から2つめの数も、この「名前の数」だよ。ずっと 1 が並んでいたあの列だね。

-rw-r--r--  2 manabiya manabiya  6  moto.txt         名前が2つある

大事なのは、どちらが本物でもないということだよ。

moto.txt ┐         ├→ inode 4(中身)kata.txt ┘

先に作ったほうが偉いわけではないんだ。まったく対等な2つの名前だよ。

03 / 08

名前を消しても中身は消えない

ここが前の回と正反対のところだよ。

~ $ ln moto.txt kata.txt~ $ rm moto.txt~ $ cat kata.txthello              ← 平気で読める!

シンボリックリンクなら壊れていたよね。ハードリンクは違うんだ。

理由は、rm の正体を知ると分かるよ。

> rm は「中身を消す」のではなく「名前を1枚はがす」

はがしたあと、残っている名前の数を数えて、0 になったときだけ中身を捨てるんだ。

rm moto.txt   → 名前は 2 → 1(中身は残る)rm kata.txt   → 名前は 1 → 0(ここで中身が消える)

だから「消したはずのファイルの容量が減らない」ということが起こるよ。他の名前が残っているとき、中身はまだ生きているんだ。

ls で見えなくなっても、中身が残っている場合がある。これを知っていると、ディスクの不思議な減らなさを説明できるようになるね。

04 / 08

シンボリックリンクとの違い

2つを並べておこう。この表がこの章の山場だよ。

シンボリックリンク(ln -sハードリンク(ln
正体指し先を書いた同じ inode の2つめの名前
指し先を消すと壊れる(迷子)平気(中身は残る)
別のディスク指せる指せない
ディレクトリ指せる作れない
ls -l の見え方l->ふつうのファイルと同じ
リンク数(%h増えない増える

見分け方で覚えるといいよ。

ls -l で -> が出る    → シンボリックリンク何も出ないが数が 2    → ハードリンク

ハードリンクは見分けがつきにくいのが弱点だね。ふつうのファイルにしか見えないんだ。

代わりに丈夫だよ。動かしても壊れないし、指し先が消えても平気だからね。

05 / 08

できないことが2つある

ハードリンクには、はっきりした制限が2つあるよ。

1. 別のディスクにはできない

~ $ ln /etc/passwd soko.txtln: soko.txt: Cross-device link

断られたね。inode 番号はそのディスクの中でだけ通じる番号だからだよ。番号 4 は「このディスクの4番」という意味で、別のディスクの4番とは無関係なんだ。

この環境だと、あなたのホームと /etc は別のディスクだよ。前の回で df の話をしたね(次の回でやるからね)。

2. ディレクトリにはできない

~ $ ln fukai fukai2ln: fukai2: Operation not permitted

これは輪ができてしまうのを防ぐためだよ。

もし作れたら…fukai/naka/fukai2 → fukai を指す → その中に fukai2 → …

終わりのない道ができてしまうでしょう。findcp -r が永久に回り続けることになる。だから禁止されているんだ。

ディレクトリを別名にしたいときは、シンボリックリンクを使ってね。

06 / 08

同じ中身の名前を全部探す

ハードリンクは見分けにくいので、探す道具を覚えておこう。

~ $ find . -samefile moto.txt./moto.txt./kata.txt

-samefile は「これと同じ inode を指しているものを出して」という指定だよ。章3でやった find の仲間だね。

リンク数が 2 以上なら、他にも名前があるということだよ。

~ $ stat -c %h moto.txt2                    ← どこかにもう1枚ある~ $ find . -samefile moto.txt(探す)

数を見て、あるなら探すという手順だね。

使いどきはこうだよ。ファイルを消したのに容量が減らないとき、

1. stat -c %h で名前の数を見る2. 2 以上なら find -samefile で残りを探す3. 全部消してはじめて容量が減る

これを知らないと、「消したのに減らない」で延々悩むことになるよ。

07 / 08

mv の正体

最後にひとつ、面白い話をしておくね。

同じディスクの中での mv は、中身を動かしていないんだ。

mv a.txt b.txt

やっているのは「札を付け替える」だけだよ。中身(inode)はそのままで、名前だけが変わる。

手でやるとこうなるね。

~ $ ln a.txt b.txt   札をもう1枚付ける~ $ rm a.txt         古い札をはがす

結果は mv a.txt b.txt と同じだよ。

だから何 GB のファイルでも、同じディスクの中なら mv は一瞬で終わるんだ。

同じディスクの mv   一瞬(札の付け替え)別のディスクへの mv  時間がかかる(本当にコピーして消す)

この差を体感したことがあるかもしれないね。USB メモリに移動すると遅いのは、そういうわけだよ。

名前と中身が別という今日の話が、ふだんの動きを説明してくれるんだ。

08 / 08

さあ、打ってみよう

この回で使うのはこれだけだよ。

ln 元 新しい名前          ハードリンクを作るstat -c %i 名前           inode 番号(中身の番号)stat -c %h 名前           名前の数(リンク数)ls -li                    番号と数を一覧でfind . -samefile 名前     同じ中身の名前を探す

stat -c の書き方だけ補っておくね。

stat -c '%i %h' 名前     2つまとめて(空白で区切って出る)

-c は「この形で出して」という指定だよ。%i%h が穴で、そこに値が入るんだ。

練習では、わざとできないこともやってみるからね。ディレクトリへのハードリンクと、別のディスクへのハードリンクだよ。

断られる形を知っていると、「なぜ -s が要るのか」が身につくからね。では打ってみよう。