The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

理解 Symbolic Link、Hard Link 與 Directory Junction 的差異之處

我經常利用不同的連結(Link)來管理檔案和目錄,以確保系統的設定隨時可以透過雲端硬碟同步與備份,相當便利。在 Windows 系統中有三種不同的連結方式,分別是 符號連結(Symbolic Link)、硬連結(Hard Link)和目錄聯接(Directory Junction)。這三種連結方式各有其特性用途,所以我打算針對這三種連結方式進行比較,幫助大家更好地理解它們之間的差異。

image

TL;DR

這裡我就以 Notepad4 應用程式為範例,來說明如何使用目錄聯接來管理應用程式的設定檔,讓特定應用程式的設定可以快速的在多台電腦自動同步設定,這也是我常用的一個技巧。

  1. 先透過 Chocolatey 安裝軟體

    choco install notepad4 -y
    
  2. 將設定檔搬移到 Dropbox 雲端硬碟

    move "%LOCALAPPDATA%\Notepad4" "%USERPROFILE%\Dropbox\Notepad4"
    
  3. 建立目錄聯接

    mklink /J "%LOCALAPPDATA%\Notepad4" "%USERPROFILE%\Dropbox\Notepad4"
    

大功告成!這樣你就可以在多台電腦上同步 Notepad4 的設定檔了。

你的第二台電腦只要這樣做:

  1. 先透過 Chocolatey 安裝軟體

    choco install notepad4 -y
    
  2. 刪除原本的設定檔

    rmdir /s /q "%LOCALAPPDATA%\Notepad4"
    
  3. 建立目錄聯接

    mklink /J "%LOCALAPPDATA%\Notepad4" "%USERPROFILE%\Dropbox\Notepad4"
    

若想要查詢特定資料夾或檔案是否為連結,可以透過 PowerShell 來查詢,以下命令可以幫助你快速找出所有已經設定好的連結:

Get-ChildItem -Path "$env:APPDATA" -Recurse -Directory | Where-Object {$_.Attributes -band [System.IO.FileAttributes]::ReparsePoint} | Format-List FullName, Mode, Target, Attributes
Get-ChildItem -Path "$env:USERPROFILE\Documents" -Recurse -Directory | Where-Object {$_.Attributes -band [System.IO.FileAttributes]::ReparsePoint} | Format-List FullName, Mode, Target, Attributes

以下正文開始:

符號連結 (Symbolic Link)

符號連結 (Symbolic Link),亦稱為軟連結 (Soft Link),是一種包含另一個檔案路徑目錄路徑的檔案,可以指向目標物件的完整路徑相對路徑

在 Windows 系統中,可以使用 mklink 命令來建立符號連結,但你需要注意的地方是,這個 mklink 並不是一個執行檔,而是在 Command Prompt (命令提示字元) 下的一個命令。

  1. 建立指向檔案的符號連結

    這個 mklink 命令的第一個參數是指定符號連結檔案的路徑,是我們即將建立的「符號連結檔」,該檔案不能已經存在。而第二個參數必須指向一個已經存在的檔案。

    mklink "符號檔案路徑" "真實檔案路徑"
    

    我以 Notepad4 設定檔為例,建立一個指向 Notepad4.ini 設定檔的符號連結:

    mklink "%LOCALAPPDATA%\Notepad4\Notepad4.ini" "%USERPROFILE%\Dropbox\Notepad4\Notepad4.ini"
    
  2. 建立指向目錄的符號連結

    你也可以將整個設定檔所在的目錄直接建立符號連結到 Dropbox 雲端硬碟的目錄,加上 /D 參數即可:

    mklink /D "%LOCALAPPDATA%\Notepad4" "%USERPROFILE%\Dropbox\Notepad4"
    

    我的作法都是先將原本路徑的檔案或資料夾,先全部用「搬移」的方式挪動到雲端硬碟,再透過符號連結的方式,將原本的路徑指向雲端硬碟的路徑

使用符號連結的時候要注意以下特性:

  • 靈活性高:可以跨越不同的檔案系統磁碟分割區,連接到網路磁碟也可以。
  • 依賴性高:若目標檔案移動刪除,符號連結將會失效,因為無法無法存取目標內容。
  • 辨識方式:在檔案總管中,符號連結通常具有特殊的圖示標示為連結,肉眼可以清晰辨識檔案或目錄是否為符號連結

硬連結 (Hard Link)

硬連結 (Hard Link) 是直接指向檔案索引節點 (inode) 的另一個目錄項目,實質上使多個檔案名稱指向同一份資料

也因為硬連結直接指向檔案索引節點 (inode),所以硬連結無法跨越不同的檔案系統磁碟分割區,且硬連結無法建立在目錄上,就只有檔案可以設定硬連結

在 Windows 系統中,你也可以使用 mklink 命令來建立硬連結,但你需要注意的地方是,這個 mklink 並不是一個執行檔,而是在 Command Prompt (命令提示字元) 下的一個命令。

在 Windows 系統中,同樣使用 mklink 命令,但需加上 /H 參數來建立硬連結:

mklink /H "硬連結檔案路徑" "真實檔案路徑"

我以 Notepad4 設定檔為例,建立一個指向 Notepad4.ini 設定檔的符號連結:

mklink /H "%LOCALAPPDATA%\Notepad4\Notepad4.ini" "%USERPROFILE%\Dropbox\Notepad4\Notepad4.ini"

使用硬連結的時候要注意以下特性:

  • 共享資料:所有的硬連結指向相同的資料,只要有至少一個連結存在,資料就不會被刪除。
  • 限制
    • 只能連結檔案,無法連結目錄。
    • 必須在同一個磁碟分割區內建立,無法跨越不同的磁碟或網路位置。
  • 透明性:硬連結從檔案總管看起來和原始檔案一樣,無法從外觀上區分。

目錄聯接 (Directory Junction)

目錄聯接 (Directory Junction) 是一種專門用於連結目錄的連結方式,允許不同磁碟分割區內的目錄相互連結。

在 Windows 系統中,你依然可以使用 mklink 命令,但需加上 /J 參數來建立目錄聯接:

mklink /J "目錄聯接路徑" "真實目錄路徑"

我以 Notepad4 設定檔為例,將設定檔的資料夾指向到 Dropbox 雲端硬碟:

mklink /J "%LOCALAPPDATA%\Notepad4" "%USERPROFILE%\Dropbox\Notepad4"

使用目錄聯接的時候要注意以下特性:

  • 目標限制:僅可連結目錄,無法連結單一檔案。
  • 同台電腦:目錄聯接必須指向本地系統內的目錄,無法指向網路位置。
  • 依賴性高:若目標目錄被移動或刪除,聯接將失效,但可以透過重新建立聯接來恢復[9][20]。

不同連結之間的差異比較

下表列出了符號連結硬連結目錄聯接之間的差異:

特性 符號連結
(Symbolic Link)
硬連結
(Hard Link)
目錄聯接
(Directory Junction
)
可連結對象 檔案目錄 僅檔案 僅目錄
跨磁碟分割 支援 不支援

支援 (僅限同台電腦)

依賴性 目標移動或刪除會導致連結失效 目標被刪除不影響,因為指向相同資料 目標移動或刪除會導致聯接失效
辨識方式 有特殊圖示標示為連結 與原檔案相同,無法區分 有特殊圖示標示為連結
創建命令 mklinkmklink /D mklink /H mklink /J
適用情境 需要跨磁碟或建立靈活連結時 在同一磁碟內需要多個檔案名稱指向同一資料 需要連結不同目錄結構,但在同一台電腦上時

透過上述比較,你可以根據實際需求選擇最適合的連結方式。我自己會這樣總結:

  • 最萬用的,就是符號連結了,沒什麼使用上的限制,有選擇障礙就選這個就好!
  • 若需在多個檔案指向同一份實體檔案內容,且限制在同一分割區內,使用硬連結則更為合適,可以減少硬碟空間耗用。
  • 如果需要連結目錄,只要是在同一台電腦上,無論幾顆硬碟、幾個磁區,選擇目錄聯接是最佳選擇。

補充一點很關鍵的知識,那就是目錄聯接對系統和應用程式來說是完全透明的,應用程式無法察覺這是一個連結,但符號連結硬連結則不同,應用程式可以察覺到這是一個連結,這是需要注意的地方。這是為什麼我都用目錄聯接來管理應用程式的設定檔的原因!👍

查詢特定資料夾或檔案是否為連結

在 Windows 系統中,你可以透過 PowerShell 來查詢目前電腦設定了多少「連結」,以下命令可以幫助你快速找出所有已經設定好的連結。例如我想查詢 $env:APPDATA 應用程式資料的目錄,已經設定了多少連結,就可以用以下命令查詢:

Get-ChildItem -Path "$env:APPDATA" -Recurse -Directory | Where-Object {$_.Attributes -band [System.IO.FileAttributes]::ReparsePoint} | Format-List FullName, Mode, Target, Attributes

附註: [System.IO.FileAttributes]::ReparsePoint 是 .NET 中 FileAttributes 列舉的一個成員,表示檔案或目錄包含重新分析點(Reparse Point)。重新分析點是一種與檔案或目錄關聯的使用者定義資料區塊,常用於實現符號連結(Symbolic Links)、目錄聯結點(Junction Points)和卷掛載點(Volume Mount Points)等功能。在 Windows、Linux 和 macOS 上,ReparsePoint 屬性均受支援。

輸出結果如下:

FullName   : C:\Users\user\AppData\Roaming\espanso
Mode       : l----
Target     : C:\Users\user\Dropbox\Tools\espanso
Attributes : Directory, ReparsePoint

...

如果想查詢我的文件夾,可以將指令改成這樣:

Get-ChildItem -Path "$env:USERPROFILE\Documents" -Recurse -Directory | Where-Object {$_.Attributes -band [System.IO.FileAttributes]::ReparsePoint} | Format-List FullName, Mode, Target, Attributes

這樣就可以查詢 $env:USERPROFILE\Documents 文件夾下的所有資料夾是否有設定連結了:

FullName   : C:\Users\user\Documents\LINQPad Plugins
Mode       : l----
Target     : C:\Users\user\Dropbox\Tools\LINQPad\LINQPad Plugins
Attributes : Directory, ReparsePoint

FullName   : C:\Users\user\Documents\LINQPad Queries
Mode       : l----
Target     : C:\Users\user\Dropbox\Tools\LINQPad\LINQPad Queries
Attributes : Directory, ReparsePoint

FullName   : C:\Users\user\Documents\LINQPad Snippets
Mode       : l----
Target     : C:\Users\user\Dropbox\Tools\LINQPad\LINQPad Snippets
Attributes : Directory, ReparsePoint

相關連結

留言評論