为 Cygwin 启用本机 NTFS 符号链接

Posted

技术标签:

【中文标题】为 Cygwin 启用本机 NTFS 符号链接【英文标题】:Enable native NTFS symbolic links for Cygwin 【发布时间】:2013-09-10 08:10:34 【问题描述】:

最近的 NTFS 和 Windows 实现了符号链接:

从 NTFS 3.0 (Windows 2000) 开始,NTFS junction point 可以用作目录符号链接,使用 linkdjunction 工具。 NTFS symbolic link 也可以用作符号链接(用于文件和目录),因为 Windows Vista 使用 mklink 工具。

但在 Cygwin 1.7(安装在 Windows 7 上)上,ln -s 会创建一个文本文件。

在 Cygwin 上:

$ ln -s -v target mylink
`mylink' -> `target'

在 MinGW(或您最喜欢的编辑器)上:

$ cat mylink
!<symlink>ÿþt a r g e t 

是否可以告诉 Cygwing 使用NTFS junction point 或NTFS symbolic link?

其他问题:MinGW 是否提供此功能?

【问题讨论】:

【参考方案1】:

⸻⸻⸻ 简答 ⸻⸻⸻

定义环境变量:

CYGWIN=winsymlinks:nativestrict

正如mwm 所指出的,您可能还必须以管理员身份运行bash。

⸻⸻⸻  长答案 ⸻⸻⸻

默认 Cygwin 符号链接只是常规文件

默认情况下Cygwin 创建文本文件作为 Windows 符号链接缺陷的解决方法。 这些文件并不是真正的symlinks。 几乎所有 Windows 程序都不将这些文件视为符号链接。

本机符号链接在最新的 Windows 版本中可用

最近的 NTFS 和 Windows 实现了符号链接:

NTFS junction point 可用作目录符号链接 从 NTFS 3.0 (Windows 2000) 开始使用 linkdjunction 工具。 NTFS symbolic link 也可以用作符号链接 (对于文件和目录)从 Windows Vista 开始使用 mklink 工具。

Cygwin 可以创建原生NTFS symlinks

Cygwin documentation 的简化摘录:

符号链接

[...]

Cygwin 可能以多种不同方式创建符号链接:

默认符号链接是包含魔法 cookie 的普通文件 后跟链接指向的路径。 [...]

快捷方式的符号链接是 Windows .lnk [...] 创建的 如果环境变量 CYGWIN [...] 设置为包含 字符串winsymlinkswinsymlinks:lnk。 [...]

本机 Windows 符号链接仅在 Windows Vista/2008 及更高版本上创建, 并且仅在支持重解析点的文件系统上。 由于它们奇怪的限制和行为,它们只被创建 如果用户明确要求创建它们。 这是通过设置环境变量 CYGWIN 包含字符串winsymlinks:nativewinsymlinks:nativestrict。 [...]

在 NFS 文件系统上,Cygwin 总是创建真正的 NFS 符号链接。

配置 Cygwin

Cygwin User's Guide 表示变量CYGWIN 和选项winsymlinks

CYGWIN 环境变量用于配置许多全局设置 [...]。 它包含下面列出的选项,以空白字符分隔。 [...]

[...] [...] [...] [...]

winsymlinks:lnk,native,nativestrict - 如果设置为 winsymlinkswinsymlinks:lnk,Cygwin 会创建符号链接 作为带有特殊标题和 R/O 属性集的 Windows 快捷方式。

如果设置为winsymlinks:nativewinsymlinks:nativestrict, Cygwin 在文件系统上创建符号链接作为本机 Windows 符号链接 和支持它们的操作系统版本。如果已知操作系统不支持 本机符号链接(Windows XP、Windows Server 2003)、警告消息 每个会话生成一次。

winsymlinks:nativewinsymlinks:nativestrict 是这样的:如果文件系统支持本机 符号链接和 Cygwin 出于某种原因无法创建本机符号链接, 它将回退到创建 Cygwin 默认符号链接 winsymlinks:native,而winsymlinks:nativestrict symlink(2) 系统调用将立即失败。

CYGWIN=winsymlinks:native 总是创建一个链接,但在目标不存在时使用 Cygwin 回退

在 Cygwin 上:

$ export CYGWIN="winsymlinks:native"
$ ln -s -v target mylink
`mylink' -> `target'
$ echo content > target

在 MinGW 上:

$ cat mylink
content

同时使用 Windows 和 Cygwin 程序的人在将符号链接创建为虚拟文件时可能会遇到问题(目标缺失时 Cygwin 回退)...

CYGWIN=winsymlinks:nativestrict 始终使用本机 Windows 符号链接,但在目标不存在时失败

在 Cygwin 上:

$ export CYGWIN="winsymlinks:nativestrict"
$ rm -f  a b
$ ln -sv a b
ln: failed to create symbolic link `b': No such file or directory
$ touch    b
$ ln -sv a b
ln: failed to create symbolic link `b': File exists
$ rm b
$ touch a
$ ln -sv a b
`b' -> `a'

由于 nativestrict 要求目标在创建符号链接之前存在,因此某些命令/脚本在创建链接时可能会失败。

注意:只有管理员才能创建本地 NT 符号链接 所以在 Windows UAC 下,Cygwin 终端仿真器 (mintty) 应该以提升的权限运行 (右键单击快捷方式并选择以管理员身份运行 或设置 mintty 快捷方式属性,高级 → 以管理员身份运行)。

特别感谢 Guria 和 Spooky 的贡献。

【讨论】:

我刚刚对这个内容丰富的答案投了赞成票。我还添加了一个建议的编辑,即启用了 UAC 的用户应该以提升的权限运行 mintty,以便能够创建本机 NT 符号链接。 export CYGWIN="winsymlinks:nativestrict" 在 Windows 8 中为我工作 对于 MSYS2,在 /msys2_shell.bat 中取消注释 set MSYS=winsymlinks:nativestrict 这在我的系统上不起作用。唯一的方法是通过cmd /c ... 关于nativestrict 含义的信息不准确。引用Cygwin User Guide: winsymlinks:native 和 winsymlinks:nativestrict 之间的区别是:如果文件系统支持本机符号链接并且 Cygwin 由于某种原因无法创建本机符号链接,它将回退到创建 Cygwin 默认符号链接winsymlinks:native,而使用 winsymlinks:nativestrict 时,symlink(2) 系统调用将立即失败。 我个人使用的是nativestrict,到目前为止没有任何失败。【参考方案2】:

公认的答案是正确的,两个小注解。

如果您只关心自己在命令行上创建的符号链接,请安装 cygutils-extra 软件包,它包含一个 winln 命令,其语法与 ln 相同,但会创建本机 Windows 链接。创建一个别名:alias ln=winln(仅适用于交互式 shell),或者甚至将 ln 文件替换为 winln(也适用于 shell 脚本) - 但它可能会在下次更新 coreutils 包时被覆盖.

我只是在我已经安装了 Cygwin 后才发现可以使用本机符号链接,并且我自己也添加了一些符号链接。所以在我将CYGWIN=winsymlinks:native 设置为我的系统环境变量之后,我想将所有现有的非本地链接转换为本地链接。这就是我所做的。

以防万一,请先备份整个 Cygwin 目录。

查找所有符号链接并将列表保存到/links 文件: cd /; find . -regextype egrep -regex './(dev|proc|mnt|cygdrive)' -prune -o -type l -print &gt;links

查看links。 创建一个包含所有链接的tar 存档:tar c --files-from=links &gt;links.tar

提取tar 存档:tar x --files-from=links &lt;links.tar 由于现在启用了本机符号链接,因此 tar 将使用本机符号链接覆盖旧 Cygwin 的符号链接。

清理:rm -f links links.tar

附:起初我使用CYGWIN=winsymlinks:nativestrict,但后来我发现在这种模式下,如果target 不存在,ln -s target link 会失败。相比之下,native 将创建一个 Cygwin(非本地)符号链接 link 指向不存在的 target - 这与 UNIX 系统上的 ln 的行为相匹配。在极少数情况下,nativestrict 可能会破坏某些程序或脚本,例如 Gentoo run-crons 脚本使用锁定文件,它是指向正在运行进程的 PID 的符号链接。在nativestrict 模式下,脚本停止工作,因为它无法再创建锁定文件。注意:run-crons 是 Gentoo Linux 上的一个 crontab 帮助脚本,增加了对cron.hourly,daily,weekly,monthly/ dirs 的支持,它与 Cygwin 配合得很好。

【讨论】:

虽然这确实有效(首先我们需要editrights -u $USER -a SeCreateSymbolicLinkPrivilege),但这种符号链接与mklink 创建的符号链接并不完全相同。基本上 CMD 的 mklink 不尊重该权限设置,而 CMD 的 mklink 正确地将文件类型设置为“.symlink”,而 winln 不这样做。效果基本上是,当由 Windows Explorer 和 Cygwin 的 ls 呈现时,符号链接实际上看起来像符号链接,当使用 mklink 时,他们知道它是 Windows 符号链接。 您是在谈论 winln 还是 tar 使用 CYGWIN=winsymlinks:nativestrict 创建的符号链接。我并没有真正使用 winln,所以无法发表评论,但在后一种情况下,由 Cygwin 创建的符号链接看起来像 Explorer 等中的符号链接。 我说的是winln。刚才试了一下。 CYGWIN=winsymlinks:nativestrict 以前对我完全不起作用。 好的,我刚刚试过mklink fzf-mklink fzfwinln -s fzf fzf-winlnln -s fzf fzf-ln(设置了winsymlinks:nativestrict)。创建的所有三个链接都显示为.symlink,在资源管理器中键入并指向同一个文件 fzf。我能看到的唯一区别是 mklink 创建的链接归 BUILTIN\Administrators 所有,而 Cygwin 创建的两个链接都归 Alpha\root(当前用户)所有。 CYGWIN=winsymlinks:nativestrict 现在是否适合您?如果不是,您如何定义该变量?【参考方案3】:

因为@olibre 的回答对我不起作用。我刚刚创建了一个 shell 函数。

: '
mklink - Create NTFS (Windows) links that is usable by Windows and Cygwin

Usage: mklink [/D | /H | /J] <link-path> <target-path>

Options:
    /D    Directory Symbolic Link
    /H    Hardlink
    /J    Directory Junction (you should prefer /D)

With no options, it creates a NTFS file symlink.
'
mklink () 

    if [ "$#" -ge "3" ]; then
        cmd /c mklink "$1" "$(cygpath --windows --absolute "$2")" "$(cygpath --windows --absolute "$3")"
    else
        cmd /c mklink "$(cygpath --windows --absolute "$1")" "$(cygpath --windows --absolute "$2")"
    fi


请注意,您需要管理员权限(对于 Cygwin)才能正常运行上述内容。

请注意,我不知道符号链接到绝对路径与使用 CMD 的 mklink 符号链接到相对路径之间是否有任何区别。在 Linux 上,如果您决定移动符号链接或移动目标文件,或同时移动两者,这两种行为会有所不同。

【讨论】:

不错的选择 :-) 请提供您已在其上测试过您的脚本以帮助其他 SO 读者的 Windows 版本(可能还有 Cygwin/MinGW)。谢谢;-) cygutils-extra 包包含一个winln 命令,该命令提供类似ln 的语法来创建Windows 本地链接。 啊,这个工具很棒。它甚至建议:editrights -a SeCreateSymbolicLinkPrivilege -a $YOUR_USER. 但实际上应该是editrights -u $USER -a SeCreateSymbolicLinkPrivilege 由于我是管理员,所以没有向我建议。【参考方案4】:

我想最简单的方法是

    从本地组策略编辑器授予 SeCreateSymbolicLinkPrivilege(gpedit.msc,默认在路径上,非家庭版本)

    在路径(批处理或 bash)上创建名为 ln 的脚本,实现 类似于上述的shell函数

    利润

【讨论】:

【参考方案5】:

您可能正在寻找一种方法来使用 MSYS 到达目录树中的另一个目的地。有一种方法。您应该创建一个包含以下行的 shell 脚本(“*.sh”文件):

cd "/drive_letter/SubCatalogue/SubFolder/..." 

【讨论】:

您好 FreeCodeRide。感谢您的想法,但我不确定是否理解。请举个例子。例如,您可以创建一个目标文件,然后创建一个链接到该目标文件的文件……干杯;)

以上是关于为 Cygwin 启用本机 NTFS 符号链接的主要内容,如果未能解决你的问题,请参考以下文章

更改 mingw 的启动目录或创建 mingw 符号链接

Ntfs 下的链接符号创建

如何列出 NTFS 文件系统上的所有符号链接

获取符号链接目标的卷名的最佳方法 [NTFS]

NTFS 连接与符号链接(用于目录)[关闭]

NTFS 连接点和符号链接有啥区别?