🏷️

ハードリンクとシンボリックリンクを説明できるようになる

2024/10/28に公開

前提

今回はUbuntuで説明します

$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=24.04
DISTRIB_CODENAME=noble
DISTRIB_DESCRIPTION="Ubuntu 24.04.1 LTS"

説明

ハードリンク

ハードリンクとは、「ファイル名と保存されているデータを紐づけるもの」です。

つまり、「保存されたデータに名前を付けるもの」です。

また、ハードリンクは同一ファイルシステムの保存されたデータに紐づける必要があります。

Every file on the Linux filesystem starts with a single hard link. The link is between the filename and the actual data stored on the filesystem.

引用:Red Hatブログ

ハード・リンクは、単にリンクと呼ばれることもあり、 実際のオブジェクトにリンクしていなければなりません。

(ファイルをディレクトリーにコピーするなどの方法で) ディレクトリー内にオブジェクトが作成されると、 ディレクトリーとオブジェクトの間に最初のハード・リンクが設定されます。

引用:IBM:ハードリンク

実演

this is sample と記載されている sample.txt を作成します。

$ echo "this is sample" > sample.txt
$ ls -li
total 4
655373 -rw-rw-r-- 1 ubuntu ubuntu 15 Oct 23 07:47 sample.txt
$ cat sample.txt
this is sample
$ stat sample.txt
  File: sample.txt
  Size: 15        	Blocks: 8          IO Block: 4096   regular file
Device: 252,0	Inode: 655373      Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1000/  ubuntu)   Gid: ( 1000/  ubuntu)
Access: 2024-10-23 10:51:14.361429275 +0000
Modify: 2024-10-23 10:41:50.210205054 +0000
Change: 2024-10-23 10:41:50.210205054 +0000
 Birth: 2024-10-23 10:41:50.210205054 +0000

このコマンドの裏でLinuxのファイルシステムが、ストレージに保存された this is sample というデータにsample.txtという名前を付けるハードリンクを作成しています。

さらに追加でハードリンクを作成してみます。

$ ln sample.txt sampleHardLink
$ ls -li
total 8
655373 -rw-rw-r-- 2 ubuntu ubuntu 15 Oct 23 07:47 sample.txt
655373 -rw-rw-r-- 2 ubuntu ubuntu 15 Oct 23 07:47 sampleHardLink
$ cat sampleHardLink
this is sample
$ stat sampleHardLink
  File: sampleHardLink
  Size: 15        	Blocks: 8          IO Block: 4096   regular file
Device: 252,0	Inode: 655373      Links: 2
Access: (0664/-rw-rw-r--)  Uid: ( 1000/  ubuntu)   Gid: ( 1000/  ubuntu)
Access: 2024-10-23 10:51:14.361429275 +0000
Modify: 2024-10-23 10:41:50.210205054 +0000
Change: 2024-10-24 05:57:54.821199900 +0000
 Birth: 2024-10-23 10:41:50.210205054 +0000

これにより、 this is sample のデータに sampleHardLink という名前を付けるハードリンクが作成されました。

lsコマンド出力のinode番号(-rw-rw-r--の前の数字)も同じ655373を指し示しています。

さらに、lsコマンド出力のLinks(-rw-rw-r--の後の数字)も1 -> 2に増えています。 (statコマンド出力のLinksでも確認可)

ここで sample.txt を消すとどうなるでしょうか?

試してみましょう。

$ rm sample.txt
$ ls -li
total 4
655373 -rw-rw-r-- 1 ubuntu ubuntu 15 Oct 23 09:02 sampleHardLink

sample.txt の名前だけが消えて、sampleHardLink の名前だけが残る形となりました。

lsコマンド出力のLinks(-rw-rw-r--の後の数字)も2 -> 1に減っています。

余談ですが、データは自身へのハードリンクが全て削除された時に、ドライブから削除されます。
つまり、自分に付けられた名前(Links)がすべてなくなった時にデータが削除されます。

$ rm sampleHardLink
$ ls -li
total 0

The data is only removed from your drive when all links to the data have been removed.

引用:Red Hatブログ

シンボリック・リンク

シンボリックリンクとは、直訳すると「抽象的なリンク」です。

抽象的なリンクなので、保存されたデータでなくても名前を付けることができます。
ディレクトリやファイルディスクリプタなどの特殊ファイルにも名前を付けることができます。

誤解を恐れずに言うと「名前に付ける名前」みたいなものです。

シンボリックリンクは複数のファイルシステムにまたがることができます。

Commonly referred to as symbolic links, soft links link together non-regular and regular files.

They can also span multiple filesystems.

引用:Red Hatブログ

シンボリック・リンクは、ファイルに含まれるパス名であり、ソフト・リンクとも呼ばれます。

引用:IBM:シンボリックリンク

実演

ハードリンクと同じ状況にします。

this is sample と記載されているsample.txtを作成します。

$ echo "this is sample" > sample.txt
$ ls -li
total 4
655373 -rw-rw-r-- 1 ubuntu ubuntu 15 Oct 23 03:09 sample.txt
$ cat sample.txt
this is sample
$ stat sample.txt
  File: sample.txt
  Size: 15        	Blocks: 8          IO Block: 4096   regular file
Device: 252,0	Inode: 655373      Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1000/  ubuntu)   Gid: ( 1000/  ubuntu)
Access: 2024-10-23 10:51:14.361429275 +0000
Modify: 2024-10-23 10:41:50.210205054 +0000
Change: 2024-10-23 10:41:50.210205054 +0000
 Birth: 2024-10-23 10:41:50.210205054 +0000

それではシンボリックリンクを貼ってみます。

$ ln -s sample.txt sampleSymbolicLink
$ ls -li
total 4
655373 -rw-rw-r-- 1 ubuntu ubuntu 15 Oct 23 10:41 sample.txt
655375 lrwxrwxrwx 1 ubuntu ubuntu 10 Oct 23 10:50 sampleSymbolicLink -> sample.txt
$ cat sampleSymbolicLink
this is sample
$ stat sampleSymbolicLink
  File: sampleSymbolicLink -> sample.txt
  Size: 10        	Blocks: 0          IO Block: 4096   symbolic link
Device: 252,0	Inode: 655375      Links: 1
Access: (0777/lrwxrwxrwx)  Uid: ( 1000/  ubuntu)   Gid: ( 1000/  ubuntu)
Access: 2024-10-23 10:50:28.746456839 +0000
Modify: 2024-10-23 10:50:26.815458100 +0000
Change: 2024-10-23 10:50:26.815458100 +0000
 Birth: 2024-10-23 10:50:26.815458100 +0000

シンボリックリンクのリンク先が sample.txt であることがわかります。

lsコマンドの出力からLinksは1のまま変わらず、inode番号も655373655375で異なります。

シンボリックリンクを削除しても元のファイル等は削除されません。

$ rm sampleSymbolicLink
ls -li
total 4
655373 -rw-rw-r-- 1 ubuntu ubuntu 15 Oct 23 10:41 sample.txt
$ cat sample.txt
this is sample

シンボリックリンクはディレクトリにも貼ることができます。

$ ln -s /dev/fd/ sampleDir
ls -li
total 4
655373 -rw-rw-r-- 1 ubuntu ubuntu 15 Oct 23 10:41 sample.txt
655376 lrwxrwxrwx 1 ubuntu ubuntu  8 Oct 23 11:04 sampleDir -> /dev/fd/
$ ls -li sampleDir/
total 0
36771 lrwx------ 1 ubuntu ubuntu 64 Oct 23 11:04 0 -> /dev/pts/0
36772 lrwx------ 1 ubuntu ubuntu 64 Oct 23 11:04 1 -> /dev/pts/0
36773 lrwx------ 1 ubuntu ubuntu 64 Oct 23 11:04 2 -> /dev/pts/0
36774 lr-x------ 1 ubuntu ubuntu 64 Oct 23 11:04 3 -> /proc/18762/fd
36775 lr-x------ 1 ubuntu ubuntu 64 Oct 23 11:04 63 -> 'pipe:[24058]'

ちなみに、シンボリックリンクは実態がないものにも貼ることができます。

$ ln -s notExist sampleNotExist
$ ls -li
total 4
655373 -rw-rw-r-- 1 ubuntu ubuntu 15 Oct 23 10:41 sample.txt
655376 lrwxrwxrwx 1 ubuntu ubuntu  8 Oct 23 11:04 sampleDir -> /dev/fd/
655377 lrwxrwxrwx 1 ubuntu ubuntu  8 Oct 23 11:15 sampleNotExist -> notExist
$ cat sampleNotExist
cat: sampleNotExist: No such file or directory
$ stat sampleNotExist
  File: sampleNotExist -> notExist
  Size: 8         	Blocks: 0          IO Block: 4096   symbolic link
Device: 252,0	Inode: 655377      Links: 1
Access: (0777/lrwxrwxrwx)  Uid: ( 1000/  ubuntu)   Gid: ( 1000/  ubuntu)
Access: 2024-10-25 04:29:56.213534050 +0000
Modify: 2024-10-23 11:15:32.574498481 +0000
Change: 2024-10-23 11:15:32.574498481 +0000
 Birth: 2024-10-23 11:15:32.574498481 +0000

まとめ

シンボリックリンクとハードリンクについてまとめてみました。

少しでも学びになってもらえれば嬉しいです。

参考

ハードリンク

シンボリック・リンク

ふつうのLinuxプログラミング 第2版 第10章

レバテック開発部

Discussion