WindowsのNTFSファイルシステムで、サポートされているファイルリンクとして、ハードリンクとジャンクションとシンボリックリンクがあります。
それぞれについての理解をまとめます。
ドキュメント
マイクロソフトのドキュメント
ハードリンク
ハードリンクは同一ボリューム内の1つのファイルに対して、複数のパスを作ることができます。
ファイルに対して作成するものとなり、ディレクトリに対してハードリンクを作成する事はできません。
複数パスを作ることにより、作成したすべてのファイルパスが削除されるまで削除されず、ハードリンクが一つでも残されていれば引き続きアクセスする事ができます。
例としてはc:/temp/file/dir-origin/file-origin.txt というオリジナルのファイルに対して、ハードリンクC:\temp\file\hardlink.txtを作成して確認してみます。
# c:\temp\file\dir-origin を作成
# file-origin.txtを作成
New-Item -ItemType File -Path C:\temp\file\dir-origin\file-origin.txt -Value HelloWorld -Force
# hardlinkを作成
New-Item -ItemType HardLink -Path C:\temp\file\hardlink.txt -Target C:\temp\file\dir-origin/file-origin.txt
作成したhardlink.txt側をテキストエディタで開いて変更後、origin.txt側を開くとhardlink.txt実施した変更が反映される事を確認できます。
fsutil file queryfileid <<ファイルパス>>で実際に格納されている場所File IDが取得できるようなので確認してみます。
fsutil file queryfileid C:\temp\file\dir-origin\file-origin.txt
fsutil file queryfileid C:\temp\file\hardlink.txt
file-origin.txtとhardlink.txtのFile IDが同じ値である事を確認できます。
ジャンクション
ジャンクション(ソフトリンク)は同一のコンピュータ上のディレクトリに対して、リンクを作成する機能となり。
ハードリンクとは異なり、ディレクトリのみを対象として作成する事ができます。
あくまでリンクとなるため参照先となるファイルが削除される、ディレクトリ名が変更されると作成したジャンクションからリンク先へアクセスする事はできなくなります。
また参照先の指定については絶対パスのみ利用する事ができます。
# ジャンクションの作成
New-Item -ItemType Junction -Path C:\temp\file\junction -Target C:\temp\file\dir-origin
C:\temp\file\junctionにアクセスすると、file-origin.txtが存在して先程作成した、c:\temp\file\dir-originにリンクされている事がわかるかと思います。
fsutil file queryfileid C:\temp\file\dir-origin
fsutil file queryfileid C:\temp\file\junction
下記画像のようにすべてのFile IDが別物となっており、ハードリンクとは違う事がわかります。
シンボリックリンク
シンボリックリンクは、ハードリンク、ジャンクションとは異なりファイル、ディレクトリ問わずにリンクを作成する事ができます。
基本的には、作成に管理者権限が必要となります。
またジャンクションとは異なり、参照先を絶対パスだけではなく相対パスでも記述する事ができます。
# 絶対パスでシンボリックリンクを作成
New-Item -ItemType SymbolicLink -Path C:\temp\file\symbolic-absolute-dir -Target C:\temp\file\dir-origin
New-Item -ItemType SymbolicLink -Path C:\temp\file\symbolic-absolute-file.txt -Target C:\temp\file\dir-origin\file-origin.txt
# 相対パスでシンボリックリンクを作成
New-Item -ItemType SymbolicLink -Path C:\temp\file\symbolic-relative-dir -Target .\dir-origin
New-Item -ItemType SymbolicLink -Path C:\temp\file\symbolic-relative-file.txt -Target ./dir-origin/file-origin.txt
fsutil file queryfileid C:\temp\file\dir-origin
fsutil file queryfileid C:\temp\file\dir-origin\file-origin.txt
fsutil file queryfileid C:\temp\file\symbolic-absolute-dir
fsutil file queryfileid C:\temp\file\symbolic-absolute-file.txt
fsutil file queryfileid C:\temp\file\symbolic-relative-dir
fsutil file queryfileid C:\temp\file\symbolic-relative-file.txt
下記画像のようにすべてのFile IDが別物となっており、ハードリンクとは違う事がわかります。
おまけ fsutil usnを確認してみる
fsutil usn readdata c:\temp\file\dir-origin | findstr ^FileRef#
fsutil usn readdata c:\temp\file\dir-origin\file-origin.txt | findstr ^FileRef#
fsutil usn readdata c:\temp\file\junction | findstr ^FileRef#
fsutil usn readdata c:\temp\file\hardlink.txt | findstr ^FileRef#
fsutil usn readdata c:\temp\file\symbolic-absolute-dir | findstr ^FileRef#
fsutil usn readdata c:\temp\file\symbolic-absolute-file.txt | findstr ^FileRef#
fsutil usn readdata c:\temp\file\symbolic-relative-dir | findstr ^FileRef#
fsutil usn readdata c:\temp\file\symbolic-relative-file.txt | findstr ^FileRef#
| Name | FileRef |
|---|---|
| dir-origin | FileRef# : 0x00000000000000000029000000036159 |
| dir-origin\file-origin.txt | FileRef# : 0x0000000000000000001a000000037837 |
| junction | FileRef# : 0x00000000000000000029000000036159 |
| hardlink.txt | FileRef# : 0x0000000000000000001a000000037837 |
| symbolic-absolute-dir | FileRef# : 0x00000000000000000029000000036159 |
| symbolic-absolute-file.txt | FileRef# : 0x0000000000000000001a000000037837 |
| symbolic-relative-dir | FileRef# : 0x00000000000000000029000000036159 |
| symbolic-relative-file.txt | FileRef# : 0x0000000000000000001a000000037837 |
各ファイルについて確認してみる
Get-ChildItemで取得できる構造のLinkTypeを参照すると、ハードリンクなのかジャンクションなのかシンボリックリンクなのか判別する事ができます。
Get-ChildItem -Recurse | Select-Object fullname , LinkType | sort FullName
総評
ジャンクションとハードリンク。 シンボリックリンク については実際に作成してみて確認するのがわかりやすいのでおすすめ。




