Windows支持4种”链接”机制,分别是shortcut、hard link、junction point、symbolic link。本文针对这4种机制进行简要介绍,可作为速查手册存在。
先吐个槽,天朝很多与本问题相关的技术文章,在术语层面相当混乱,作者的一知半解以及不使用规范术语,给本就容易混淆的概念带来更大的误导。
-------------------------------------------------------------------------- 1) shortcut/快捷方式 以.lnk文件方式存在,适用于Explorer等应用程序。 非NTFS内置机制,从Win95开始得到支持。FAT32支持。 同时适用于文件、目录。 只能使用绝对路径。 可以跨盘符,可以跨主机,可以使用UNC路径、网络驱动器。 删除shortcut,不影响target。 -------------------------------------------------------------------------- 2) (file) hard link 假设本文读者具有*nix基础,此处不做hard link的语义解释。 NTFS内置机制,从Windows NT 4开始得到支持。FAT32不支持。 只适用于文件。 只能使用绝对路径。 hard link与target file必须位于同一volume,可以简单理解成不能跨盘符。 在Explorer中删除hard link,不影响target file。 删除target file,不影响hard link。事实上由于hard link的语义,此时剩下的 hard link就是原始数据的唯一访问点。 相关Win32 API: CreateHardLink() CreateHardLinkTransacted() 创建: mklink /H "hard link name" "target file" fsutil.exe hardlink create "hard link name" "target file" 查看: fsutil.exe hardlink list "hard link name" fsutil.exe hardlink list "target file" 二者效果一样,hard link的语义本就如此。 -------------------------------------------------------------------------- 3) (directory) junction point/soft link/reparse point junction point也叫soft link,这是微软官方文档里说的: Hard Links and Junctions https://msdn.microsoft.com/en-us/library/windows/desktop/aa365006 junction point的底层机制是NTFS的reparse point: Reparse Points https://msdn.microsoft.com/en-us/library/windows/desktop/aa365503 Junction v1.06 http://www.sysinternals.com http://technet.microsoft.com/en-us/sysinternals/default.aspx https://technet.microsoft.com/en-us/sysinternals/bb896768 How to create and manipulate NTFS junction points https://support.microsoft.com/en-us/kb/205524 NTFS内置机制,从Windows 2000/XP开始得到支持。 只适用于目录。Vista的"C:\Documents and Settings\"是指向"C:\Users\"的 junction point,这样一些使用了硬编码"C:\Documents and Settings\"的老程序可 以在Vista上正常工作。 只能使用绝对路径。即使创建junction point时使用了相对路径,保存到NTFS中时将 隐式转换成绝对路径。 junction point必须与target directory位于同一local computer,可以简单理解成 不能跨主机。不能使用UNC路径;假设Z是通过网络映射生成的盘符,同样不适用于Z。 在local computer范围内,可以跨盘符。 在Explorer中删除junction point,有两种情况。对于Windows 2000/XP/2003,会同 步删除target directory,这真是一个奇葩的行为。注意,我们强调,在Explorer中 删除,高版本的Total Commander没有这个奇葩行为。对于Vista及之后版本,不影响 target directory,这才是人类所能理解的行为。 删除target directory,junction point仍将存在,但失效了,变得不可用。这个很 好理解,因为此时junction point指向不存在的目录。 diskmgmt.msc 右键选中某volume 更改驱动器号和路径 添加 装入以下空白NTFS文件夹中 这个功能用的就是junction point机制,还可以用mountvol.exe完成操作。 创建: mklink /J "junction point name" "target directory" // 生成的Reparse Data相比junction.exe要多 linkd.exe "junction point name" "target directory" // Windows Resource Kits 查看: dir /A:L /S "path" fsutil.exe reparsepoint query "junction point name" // 有Reparse Data的16进制转储 linkd.exe "junction point name" // 不能查看junction.exe生成的"junction point" 删除: fsutil.exe reparsepoint delete "junction point name" // 不建议使用 linkd.exe "junction point name" /D // 可以删除junction.exe生成的"junction point" 它这个行为不是我们期望的效果,比如"target directory"下有普通文件,上述命令 会删除"junction point"下的普通文件,但不会删除"junction point",同时 "target directory"下的普通文件仍然存在。这个效果我不能理解。在Explorer中操 作无法达到这种效果。 sysinternals的junction.exe: junction.exe "junction point name" "target directory" // 创建 junction.exe "junction point name" // 查看 junction.exe -q -s "path" // 递归查看 junction.exe -d "junction point name" // 删除 我猜junction.exe提供-d参数,就是因为Windows 2000/XP/2003的Explorer奇葩行为, 这个-d不影响target directory。 示例: "dir /A:L /S c:\ 2009/07/14 13:08 "JUNCTION" Documents and Settings [C:\Users] "junction.exe "C:\Documents and Settings" C:\Documents and Settings: JUNCTION Print Name : C:\Users Substitute Name: C:\Users "junction.exe -q -s c:\ \\?\c:\\Documents and Settings: JUNCTION Print Name : C:\Users Substitute Name: C:\Users -------------------------------------------------------------------------- 4) symbolic link Symbolic Links https://msdn.microsoft.com/en-us/library/windows/desktop/aa365680 symbolic link不是soft link,不要跟着SB瞎起哄。 NTFS内置机制,从Vista开始得到支持。 同时适用于文件、目录。这是一种超级shortcut。 可以使用相对、绝对路径。假设创建symbolic link时使用了相对路径,保存到NTFS 中的就是相对路径,不会隐式转换成绝对路径。 可以跨盘符,可以跨主机,可以使用UNC路径、网络驱动器。 在Explorer中删除symbolic link,不影响target。 删除target,symbolic link仍将存在,但失效了,变得不可用。 相关Win32 API: CreateSymbolicLink() CreateSymbolicLinkTransacted() 创建: mklink "file symbolic link name" "target file" mklink /D "directory symbolic link name" "target directory" 注意不指定/D时创建file symbolic link,指定/D创建directory symbolic link。 --------------------------------------------------------------------------