前言


對於 Windows 系統的上連結 (link)功能, 一直以來我都只是照著小抄輸入指令, 沒有太深入的研究. 直到最近在 VM 上測試 git 的一些進階功能時, 遇到一些需要使用連結的地方, 吃到了苦頭, 才下定決心研究清楚. 因此產出了這一篇貼文.

Windows 的檔案系統與連結


如果用基礎架構來區分 MS Windows 用過的磁碟檔案系統, 可以分為 FAT 及 NTFS 二大類.

  • FAT 類有: DOS 年代檔名是 8.3 格式的 FAT12, FAT16; 擴充長檔名功能給 OS/2 用的 HPFS; Windows 95/98 用的 vFAT, FAT32; 以及目前最新的適用於 flash 的 exFAT.
  • NTFS 類: 則是整個重新設計給 Windows NT 平台用的. 從 Windows NT 3.1 開始成為 Windows NT 家族的標準檔案系統 (NTFS 版本 v1.0). 雖然它也是一直在擴充功能, 但是只在版本號碼上改變, NTFS 這個名稱一直沒變.

FAT 基本上是沒有連結的功能(註一, 註二); 即便是 NTFS 也一直到 NTFS v3.0(註三) 才開始提供連結 (link) 的功能. 因此, 想要在 Windows 上建立連結, 你用的 Windows 作業系統必需至少是 Windows NT 4.0 + Service Pack 4; 若是伺服器則必需是 Windows Server 2000 以上; 一般家用電腦的使用者則必需是 Windows XP (用的是 NTFS v3.1) 以上 (含); 同時你用的磁碟格式也必需選用是 NTFS 才行. 現下常用的 Win10, Win7 只要是 NTFS 格式的磁碟我們都可以在上面建立連結.

註一: 雖然理論上也是可以提供的, 但是微軟當年就是沒想要在 FAT 系統上實作這個功能的意思.

註二: Windows 95 雖然有 .lnk 檔, 看起來好像是一個連結, 但它並無法真正的完成連結的功能: 基本上只有 Windows '檔案總管' 看得懂它. 它對許多 Windows 的應用程式和舊的 DOS 程式都依然只是一個看不懂的 .lnk 檔.

註三: NTFS 版本資訊有個小小的問題: NTFS v3.0 是指 NTFS 的格式版本, 但是因為 NTFS.sys 的版本被標示為 5.0, 所以一般它又被稱為 NTFS 5.0. 同樣的目前最新的格式版本 NTFS v3.1 也被稱為 NTFS 5.1. 參閱維基百科 Wikipedia NTFS

關於 Link


連結一般分為 '硬連結' (hard link) 和 '符號連結' (symbolic link) (或者為了對稱有人用 '軟連結' (soft link)).

硬連結 (hard link) 是在實體的目錄區裡配置了一個檔案 (所以有獨立的檔名及屬性...), 但卻和原本的檔案共用磁區配置表 (所以實體的檔案內容只有一份). 同時為了維護檔案刪除的功能, 磁區配置表會多記錄一個參照計數的資訊 (意即該檔案在目錄區有幾個進入點):

  • 每個檔案的參照計數值預設為 1;
  • 每次在一個檔案上建立硬連結時, 該檔案的參照計數值即 +1;
  • 刪除該檔案 (或者它的硬連結) 時並不真的刪除檔案, 只是在目錄裡清除該檔的進入點, 並將它的參照計數值 -1; 當參照計數值為 0 時才真的刪除該檔案.

硬連結最大的限制是: 來源及目標檔案都要在同一個磁區分割 (partition)(註四). 這是因為檔案系統一般是以 partition 為單位來掛載, 如果硬連結跨越了 partition, 到時候可能因為實際存放檔案的 partition 沒有連在系統上, 進而造成檔案存取失敗. NTFS 上的硬連結也差不多是這樣的實作.

原本硬連結的概念是可以套用到目錄的, 但由於容易在實體檔案系統上製造出無限循環的目錄結構, 因此被棄置了. 不過連結目錄的需求是真實存在的, 所以後來改以符號連結 (symbolic link)來替代.(註五)

NTFS 在 v3.0 時則因為還沒有支援符號連結 (Symbolic Link) 功能, 因此弄了一個名為 Junction 的功能來替代. 後來 NTFS v3.1 提供符號連結的功能 (基於原本的 Junction 同時進行了一些改良), 但是原本 Junction 的功能並沒有被取消.(註六)

註四: 這裡應該說是 '在同一個掛載單元 (mount unit) 上'. 以 NTFS 來說, 如果沒有使用 volume 時, 最小單元是 partition. 有使用 volume 時則, 最小單元就會變成是 volume.

註五: 使用符號連結 (symbolic link)或者所謂的軟連結 (soft link)時, 在檔案系統上看似依然會有無限循環的目錄結構. 但只要關閉或者是忽略不處理 "連結的重新導向 (繞路) 功能", 檔案系統的實體中並不會也沒有無限循環的目錄結構.

註六: 關於 NTFS Symbolic Link 和 Junction 之間的細微的不同, 後面有詳細的說明.

指令與操作


指令部份 Win7 之後的版本有內建的 mklink.exe 指令可用. Windows XP 或之前的版本用的指令是 linkd.exe, 需要額外下載及安裝 Windows Server 2003 Resource Kit Tools 才能使用; 如果需要的只是 junction, 也可以用這個名為 Junction 的小工具來完成.

除了文字指令之外, 另外還有一個第三方的圖形化的操作介面 Link Shell Extension, 日後有空再另行介紹如何安裝及使用. 先來看看 mklink吧!

mklink 指令解說


下圖是mklink的指令說明畫面. 我們看到輸入指令時可以不帶選項或者使用 /H,/D,/J三個選項其中之一. 依據我們上一段的說明及指令說明, 我們知道:

  • 不帶選項: 用於建立檔案的符號連結.
  • /D選項: 用於建立目錄的符號連結.
  • /H選項: 用於建立檔案的硬連結.
  • /J選項: 用於建立目錄硬連結 Junction.(註七)
mklink

mklink的指令說明畫面

註七: 請不要誤認 Junction 是目錄的 hard link (我是故意打錯, 刪掉). Junction 真的不是目錄的 hard link, 在微軟的文件中是以軟連結 (soft link) 來歸類 Junction 的.

不過要注意的是: mklink指令參數檢查並不完整, 它並沒有檢查連結標的 (target) 是檔案還是目錄, 也不檢查它是否存在. 唯一有檢查的是使用/H選項時標的必需是存在的檔案. 所以它不會阻擋你在建立檔案連結時使用/D/J選項; 也不會阻擋你在建立目錄連結時不加選項. 不過還好的是錯誤的連結除了不能正常發揮連結的功能之外並不會在檔案系統引發其他問題.

mklink    <link> <target_file>
mklink /H <link> <target_file>
mklink /D <link> <target_file>   :: 指令執行 OK, 但實際的連結 NG
mklink /J <link> <target_file>   :: 指令執行 OK, 但實際的連結 NG

mklink    <link> <target_folder> :: 指令執行 OK, 但實際的連結 NG
mklink /H <link> <target_folder> :: 指令執行 NG
mklink /D <link> <target_folder>
mklink /J <link> <target_folder>

下面二個畫面所顯示的是我用 4 個不同的 '選項'-'檔名' 對應, 針對同一個標的檔案建了 4 個連結的結果. 如各位看到的: 4 個連結型態都不一樣. 其中除了用/H選項所建立出來的檔案 NEWS-h.txt 和原始檔案 NEWS.txt 可以看到檔案太小, 其他三個則都是顯示它的連結型式以及它是連結到哪一個檔案. (還有, 你注意到了嗎? Junction 所顯示的連結是絕對路徑)

mklink_file

連結 "檔案" 的執行結果畫面: Console

mklink_file-02

連結 "檔案" 的執行結果畫面: 檔案總管

請注意: 上圖中檔案 NEWS-d.txt 和檔案 NEWS-j.txt 竟然被 '檔案總管' 當作目錄了.

再下來二個畫面是標的改為目錄, 再作一遍: 我改用 4 個不同的 '選項'-'目錄名稱' 對應, 對同一個標的目錄建了 4 個連結. 結果如各位看到的: 選項/H無法用在目錄上, 其他 3 個則都可以執行成功, 3 個建好的連結也是型態各自不同. 三個也都顯示它的連結型式以及它是連結到哪一個檔案.

mklink_folder-01

連結 "目錄" 的執行結果畫面: Console

mklink_folder-02

連結 "目錄" 的執行結果畫面: 檔案總管

請注意: 上圖中目錄 Folder-s 竟然被 '檔案總管' 當作 檔案了.

我們再仔細對照這二組實驗的 4 個結果畫面, 發現實際上是指令的選項影響了指令所產生的連結型態:

  • 不加選項: 指令不加選項會建立的 Symbolic Link. 無論標的是檔案或是目錄, 建出來的型式都一樣: 在 CMD Console 顯示為 <SYMLINK>; 在 "檔案總管" 外觀看起來是一個 "檔案的捷徑" 而它的檔案類型是 .symlink. 但是只有標的是檔案的 <SYMLINK> 才能真的連結到實際的標的檔案.
  • 選項 /H: 指令加選項 /H 會建立 Hard Link. 如前述, 目錄無法建立 hard link. 而檔案的 hard link 則無論是在 CMD Console, 或是 "檔案總管" 外觀乍看之下都和實際複製出來的檔案一樣. 差異是: 修改其中一個檔案時, 另一個也跟著改了 (二者的資料內容其實是同一份)(註八).
  • 前二個用在檔案上, 選項 /D 和選項 /J 則用在目錄上. 但是同樣的, 無論標的是檔案或是目錄, 建出來的型式都一樣, 其結果在 "檔案總管" 看起來並沒有明顯差異 (但只有標的是目錄的連結有效):
    • 選項 /D 會建立目錄類的 Symbolic Link. CMD Console 顯示為 <SYMLINKD>; 在 "檔案總管" 看起來是一個 "目錄的捷徑".
    • 選項 /J 會建立 Junction. CMD Console 顯示為 <JUNCTION>; 在 "檔案總管" 看起來也是一個 "目錄的捷徑".

綜合以上說明, 對於 mklink.exe 我們有了以下的結論: 使用者必需清楚知道自己現在處理的檔案還是目錄, 想要建的連結是 hard link, Junction 還是 Symbolic Link 並選用正確的選項參數.

註八: 使用 Link Shell Extension 可以看到該檔案的參照計數, 以及和哪幾個檔案連結在一起.

注意事項及限制


檔案的 hard link 比較獨特而且限制條件多, 和其他幾個不同:

  • 建立時的限制條件是連結標的都必需在本機的同一個 partition 中.
  • hard link 建立完成之後, 目錄上的進入點各自獨立, 但資料內容是同一份 (檔案的權限及屬性也是只有一份)
  • 就檔案系統而言其實是分不清誰是檔案的標的本體, 誰是分身.
  • 因為目錄上的進入點各自獨立, 所以標的本體或分身都可以各自修改檔案名稱互不影響.
  • 標的本體/分身檔案在同一個 partition 中搬家移動也是可以的, 並不會有任何影響. 但搬到別的 partition 則實體上會變成有二份檔案, 互不相干了(註九).
  • 因為設計上有參考計數值的關係, 只把標的本體或分身其中之一刪除並不會使檔案真的不見 (對方還在, 還可以正常讀寫); 必需全部都刪除了, 檔案才會真的消失.

目錄的 Symbolic Link 基本上和 Junction 非常的類似, 你可以把 Symbolic Link 視為 Junction 的進階版: 部份特性像 hard link, 部份特性像 symbolic link.

  • 建立時的限制條件是同在本機的本地檔案系統中 (不必是同一個 partition), 但不能跨越網路.
  • Junction 連結會記住標的本體的絕對路徑, 所以連結建立後標的本體不能更名, 不能搬家, 不能刪除 (否則會造成連結參考不到標的本體). 但可以修改內容.
  • 目錄的權限及屬性和 hard link 一樣也是只有一份.
Junction 和 Symbolic Link 比較表
動作:屬性 Junction Symbolic Link
建立:跨越網路 連結與標的 (target) 必需是本機的本地檔案系統 沒有限制, 也可以是網路上的資源 (SMB, SAMBA)
建立:相對路徑 下達指令時可以用相對路徑, 但記錄下來的一定是絕對路徑 支援相對路徑
建立:需求權限 只要在目錄中有建立檔案的權限即可在該目錄中建立連結 必需要有 Administrator 權限才能建立連結 (所以你有注意到我貼的 console 圖片是 '系統管理員:命令提示字元' 嗎?)
標的 (target) 移動, 更名, 刪除 連結失效 連結失效
移動, 更名 包含標的 (target) 的上N層目錄 連結失效(註十) 連結可能失效(註十一)
連結的權限 同標的本體 可以額外的設定連結的權限
刪除連結
  • Windows XP, Windows 2000/2003: (除非使用特定工具) 連結連同其連結的標的 (target) 一併被刪除.
  • Windows Vista 以後的版本: 刪除連結本身, 標的不受影響.
刪除連結本身, 標的不受影響.

註九: 檔案在不同 partition 之間搬家, 原本實際上的動作即是: 複製 (到新的 partition) 及刪除 (原始檔案).

註十: 由於使用絶對路徑的關係, 完全不可以對標的 (target) 或包含它的任何一個上層目錄進行任何動作, 連變更磁碟機代號也不可以.

註十一: 只要移動更名 的範圍夠大, 可以維持連結和它的標的之間的相對路徑關係, 連結就不會失效.

圖形化的操作介面 Link Shell Extension 使用介紹


Windows 檔案系統上的連結 (Link) -- Part2: Link Shell Extension

參考及連結


    MagicJackTing 發表在 痞客邦 留言(3) 人氣()