﻿# 建立 NTFS Reparse Points 的方法 ( Soft Link 與 Hard Link )

最近在安裝壹台測試機，由於要架設好幾個站台，每個站台的程式部分大概有 20MB 左右而已，但是搭配著網站進行測試的相關檔案卻有將近 3GB 之多，為了可以順利測試網站這些檔案都必須存在，如果真的複製好幾份的話主機就會頓時浪費許多磁碟空間，這時就可以多加利用建立 **檔案連結**、**目錄連結** 或 **目錄連接 (Junction)** 的方式有效減少硬碟空間。

由於 Windows 主機普遍都是採用 NTFS 檔案系統，而在 NTFS 檔案系統裡有關「連結」的種類有好幾款，我第一次接觸時也是霧裡看花，不常用的人真的會搞不清楚這幾種的差別，我先來簡單介紹一下：

在 NTFS 檔案系統裡有種物件類型稱為 [NTFS reparse point](http://en.wikipedia.org/wiki/NTFS_reparse_point) (不太知道怎樣翻譯這名詞)，這是從 NTFS v3.0 也就是 Windows 2000 開始就有的東西，他可以延伸檔案系統對檔案處理的方式，只要在特定目錄或檔案上添加所謂的 [Reparse Point Tags](http://msdn.microsoft.com/en-us/library/aa365511\(v=VS.85\).aspx) 就能讓作業系統或應用程式知道要去哪裡找檔案內容。

簡單來說，[NTFS reparse point](http://en.wikipedia.org/wiki/NTFS_reparse_point) 可區分成兩大類：

**硬式連結 ( Hard Links )**

這種連結類型歷史悠久，從 NT 4.0 開始就存在了，他有一個很明顯的限制，就是要建立這種**硬式連結**其**實體檔案**與**連結**都必須位於同一個磁碟機裡，就算是同一顆硬碟不同分割區也不能跨越。

**硬式連結**在連接檔案時 (注意: NTFS 不支援目錄硬式連結)，所連結的對象並不是「參照檔案的路徑」，而是「參照檔案的 NTFS 檔案位置」，如下圖示代表著你建立完 **LINK A.TXT** 與 **LINK B.TXT** 這兩個硬式連結到特定檔案後，他實際上所指向的是磁碟實體的資料位置，並不會記憶建立連結時的檔案路徑與名稱，就算你刪除了原本建立的那個檔案，其資料也不會消失，**LINK A.TXT** 與 **LINK B.TXT** 這兩個硬式連結一樣能存取到檔案內容，只有當所有連結到實體磁碟位置的硬式連結都不見了，這個檔案區塊才會正式被宣告為未使用。

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/9b177b890072d959621e-image_1092.png)

以下我們直接舉一個實際的例子來示範其特性，我們先建立一個一般檔案 **a.txt** 然後再使用 [mklink](http://technet.microsoft.com/en-us/library/cc753194\(WS.10\).aspx) 工具 ( 註: Windows Vista 以上才有此指令 ) 建立硬式連結，建立完之後無論從 DOS 模式下或檔案總管都看不出這兩個檔案有何差異：

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/371e2023314606700c95-image_1093.png)

有趣的是，當你修改了 a.txt 的內容，其 b.txt 的內容與修改時間會跟 a.txt 完全一模一樣，但兩者的更新時間會差異個幾秒鐘，不過這並不重要，重要的是兩個檔案不管怎樣都會存取到相同檔案內容。

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/eac1b51e920abd94dea5-image_1094.png)

更好玩的是，不管你建立幾份硬式連結磁碟總使用空間都不會變多，但使用檔案總管統計檔案大小時，卻每一份都會給他算進去，因此建立了硬式連結後，磁碟的使用量統計就會有一些失真，這點是必須特別注意的地方。

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/ce03edecc16055f5e52f-image_1095.png)

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/e33f8936f51269992c7e-image_1096.png)

如果你今天使用的是 Windows Vista 以前的作業系統，例如 Windows Server 2003 或 Windows XP 之類的，要建立硬式連結就必須靠 [Fsutil hardlink](http://technet.microsoft.com/en-us/library/cc788097\(WS.10\).aspx) 命令來建立，如下圖示：

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/30c314c003f4e0ea7ee4-image_1097.png)

**軟式連結 ( Soft links )**

軟式連結最大的優點就是其連結能夠跨磁碟機建立連結，所以比硬式連結還來的彈性許多，這種連結在 Windows 2000 / XP 以前，只有一種稱為 [Junction point](http://en.wikipedia.org/wiki/NTFS_junction_point) 類型，這種類型我在幾年前曾經寫過一篇【[介紹好用工具：Junction ( Windows 版的 Soft link )](/post/2009/02/11/Using-Junction-tool-to-make-symbolic-links-in-Windows.aspx) 】文章，就是用來介紹如何利用 [Junction](http://technet.microsoft.com/en-us/sysinternals/bb896768.aspx) 工具來建立目錄的 Soft Links，其使用時的注意事項也請參考該篇文章的內容。

從 Windows Vista 開始，Windows 開始支援另一種 **符號連結** (Symbolic Link 或 SYMLINK) 的軟式連結，這種連結又比 [Junction point](http://en.wikipedia.org/wiki/NTFS_junction_point) 更加來的彈性許多，除了可以建立目錄的 Soft Link 之外，還能建立檔案的 Soft Link，不但能跨越磁碟機，甚至於還能跨伺服器的建立 Soft Link，非常具有彈性！

以 **symbolic link** (SYMLINK) 連結來說，在檔案系統中所記錄的是「參照檔案的路徑或檔名」，所以跟硬式連結最大的差異就在於，就算「參照檔案的路徑或檔名」不存在，還是能建立 **符號連結**。如下圖示，我們試圖建立一個 b.txt 的符號連結，並參考到 a.txt，即便 a.txt 檔案不存在還是能建立符號連結：

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/c0d35927f259abdf5ac4-image_1098.png)

這時你從檔案總管可以看出「符號連結」會有不同的圖示，若試圖開啟檔案他會嘗試去解析符號連結所記錄的路徑（相對路徑或絕對路徑皆可），如果找不到檔案就會回報錯誤：

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/6d48bcd34577b197ea19-image_1099.png)

\---

瞭解這兩種不同的 [NTFS reparse point](http://en.wikipedia.org/wiki/NTFS_reparse_point) 之後，最重要的還是要能解決實務上的開發問題，我希望在我們的測試機上不要有太多重複的測試檔案，我們有個目錄下有 8 萬多個檔案，合計將近 3GB，我打算這兩個站台的這些檔案只保留一份就好，另一個站台的目錄就直接用符號連結的方式建立。

比較簡單的作法，我們可以建立「目錄符號連結」最簡單，一個指令就能完成，但在使用 mklink 時要記得加上 **/D** 參數才行，如下指令與圖示：

```
mklink /D Temp_Symlink Temp
```

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/a25fc7fe6afd6bbc827c-image_1100.png)

但我們的另個站台可能會上傳不同的測試資料上去，所以必須用獨立的目錄來儲存這些檔案，因此我們必須大量的建立檔案符號連結才行。

為此我寫了一個好用的批次檔來解決這個問題。以下是批次檔的內容，使用前記得先修改 SourceDir 與 TargetDir 參數，改好之後用滑鼠點兩下即可執行完畢：

```xml
@ECHO OFF

:: 請設定來源目錄路徑
SET SourceDir=C:\Inetpub\wwwroot\Content\pictures

:: 請設定要建立【符號連結】的目錄路徑 (所有符號連結的檔案都匯放在這個目錄下)
SET TargetDir=D:\WebTest1\Content\pictures

IF NOT EXIST %SourceDir% (
  ECHO.
  ECHO 查無來源目錄: %SourceDir%
  ECHO.
  GOTO End
)

IF NOT EXIST %TargetDir% (
  ECHO.
  ECHO 查無目標目錄: %TargetDir%
  ECHO.
  GOTO End
)

:: 本批次檔必須放在 TargetDir 目錄執行
CD /D %TargetDir%

:: 取得來源目錄的所有檔案並取得檔案名稱
for /F %%F in ('dir /B %SourceDir%') do (
  :: 若檔案已存在目標路徑則自動跳過建立符號連結
  IF NOT EXIST %%F (
    mklink %%F %SourceDir%\%%F
  )
)

:End

pause
```

以下是執行時的畫面：

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/b93e9a7cf6d39846e87b-image_1101.png)

執行完後就會將所有來自於「來源目錄」下的所有檔案全部透過符號連結的方式建立到「目標目錄」下，非常之實用！ ^\_^

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/33a596ecfd6d87e1a296-image_1102.png)

**相關連結**

-   知識觀念

-   [NTFS reparse point - Wikipedia, the free encyclopedia](http://en.wikipedia.org/wiki/NTFS_reparse_point)
-   [Hard link - Wikipedia, the free encyclopedia](http://en.wikipedia.org/wiki/Hard_link)
-   [NTFS junction point - Wikipedia, the free encyclopedia](http://en.wikipedia.org/wiki/NTFS_junction_point)
-   [NTFS symbolic link - Wikipedia, the free encyclopedia](http://en.wikipedia.org/wiki/NTFS_symbolic_link)
-   [Hard Links and Junctions (Windows)](http://msdn.microsoft.com/en-us/library/aa365006\(v=VS.85\).aspx)
-   [NTFS Hard Links, Directory Junctions, and Windows Shortcuts](http://www.flexhex.com/docs/articles/hard-links.phtml)

-   工具說明

-   [Fsutil hardlink](http://technet.microsoft.com/en-us/library/cc788097\(WS.10\).aspx)
-   [Fsutil reparsepoint](http://technet.microsoft.com/en-us/library/cc785451\(WS.10\).aspx)
-   [mklink](http://technet.microsoft.com/en-us/library/cc753194\(WS.10\).aspx)
-   [Junction](http://technet.microsoft.com/en-us/sysinternals/bb896768)
-   [Link Shell Extension](http://schinagl.priv.at/nt/hardlinkshellext/hardlinkshellext.html) ( 超強的 Windows Shell 工具 )

-   其他連結

-   [The Will Will Web  介紹好用工具：Junction ( Windows 版的 Soft link )](/post/2009/02/11/Using-Junction-tool-to-make-symbolic-links-in-Windows.aspx)
-   [\[Windows\] 用mklink與junction建立資料夾連結 « 簡睿隨筆](http://jdev.tw/blog/1242/mklink-junction-quick-folders-access)

-   開發類

-   [Symbolic Links (Windows) - Creating Symbolic Links (Windows)](http://msdn.microsoft.com/en-us/library/aa363878\(v=VS.85\).aspx)
-   [Symbolic Links (Windows) - Programming Considerations (Windows)](http://msdn.microsoft.com/en-us/library/aa365460\(VS.85\).aspx)
-   [Symbolic Links (Windows) - Symbolic Link Effects on File Systems Functions (Windows)](http://msdn.microsoft.com/en-us/library/aa365682\(v=VS.85\).aspx)
-   [Symbolic Links (Windows)](http://msdn.microsoft.com/en-us/library/aa365680%28v=VS.85%29.aspx)
-   [Reparse Points](http://msdn.microsoft.com/en-us/library/aa365503\(v=vs.85\).aspx)

-   [Reparse Point Tags](http://msdn.microsoft.com/en-us/library/aa365511\(v=VS.85\).aspx)

-   [Determining Whether a Directory Is a Mounted Folder (Windows)](http://msdn.microsoft.com/en-us/library/aa363940\(v=VS.85\).aspx)

-   [File Attribute Constants (Windows)](http://msdn.microsoft.com/en-us/library/gg258117\(v=VS.85\).aspx)
