启用Cygwin的本地NTFS符号链接

56

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

  • NTFS联接点自NTFS 3.0(Windows 2000)以来可以用作目录符号链接,使用linkdjunction工具。
  • NTFS符号链接也可以用作符号链接(适用于文件和目录),自Windows Vista以来使用mklink工具。

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

在Cygwin上:

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

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

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

有没有可能告诉Cygwin使用NTFS连接点NTFS符号链接

其他问题:这在MinGW上是否可用?

5个回答

90

⸻⸻ 简短回答 ⸻⸻

定义环境变量:

CYGWIN=winsymlinks:nativestrict

正如mwm所指出的,您可能还需要进入设置或以管理员身份运行。请参见注释部分。

⸻⸻  长答案  ⸻⸻

默认的Cygwin符号链接只是普通文件

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

最近的Windows版本支持本机符号链接

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

  • NTFS连接点可以用作目录符号链接 自NTFS 3.0(Windows 2000)起使用linkdjunction工具。
  • NTFS符号链接也可以用作符号链接(对于文件和目录均适用) 自Windows Vista起使用mklink工具。

Cygwin可以创建本机的NTFS符号链接

摘自Cygwin文档

符号链接

[...]

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

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

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

  • 仅在Windows Vista/2008及更高版本上创建本机Windows符号链接, 而且仅在支持重解点的文件系统上才能创建。 由于其奇怪的限制和行为,只有用户明确请求创建它们时才会创建它们。 这是通过将环境变量CYGWIN设置为包含字符串 winsymlinks:nativewinsymlinks:nativestrict来完成的。 [...]

  • 在NFS文件系统上,Cygwin始终创建真正的NFS符号链接。

配置Cygwin

Cygwin用户指南介绍了变量CYGWIN和选项winsymlinks

环境变量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 要求在符号链接创建之前存在目标,因此创建链接时可能会导致某些命令/脚本失败。

注释

自Windows 10 Build 14972以来,通过在开发人员设置中启用开发人员模式,非提升的 shell 中可以使用本地 NTFS 符号链接。 参考:https://blogs.windows.com/windowsdeveloper/2016/12/02/symlinks-windows-10/

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

特别感谢GuriaSpookyGene Pavlovsky的贡献。


2
我刚刚点赞了这个非常有用的回答。我还添加了一个建议的编辑,建议启用UAC的用户应该使用提升的特权运行mintty,以便能够创建本地NT符号链接。 - Anthony Geoghegan
1
在Windows 8中,export CYGWIN="winsymlinks:nativestrict" 对我起了作用。 - aqavi_paracha
2
对于MSYS2,请在/msys2_shell.bat中取消注释set MSYS=winsymlinks:nativestrict - mkjeldsen
1
这在我的系统上不起作用。唯一的方法是通过 cmd /c ... - CMCDragonkai
2
nativestrict 的含义不准确。引用Cygwin用户指南:* winsymlinks:native和winsymlinks:nativestrict之间的区别在于:如果文件系统支持本地符号链接,但由于某些原因Cygwin无法创建本地符号链接,则会使用winsymlinks:native创建Cygwin默认符号链接,而使用winsymlinks:nativestrict则会立即失败符号链接(2)系统调用。*个人使用nativestrict,到目前为止没有任何失败。 - Gene Pavlovsky
显示剩余13条评论

7

这个被接受的答案是正确的,有两个小细节需要注意。

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

当我已经安装了Cygwin并自己添加了一些符号链接后,才发现可以使用本机符号链接。因此,在将CYGWIN=winsymlinks:native设置为系统环境变量后,我希望将所有现有的非本机链接转换为本机链接。以下是我的做法。

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

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

检查links。 创建一个包含所有链接的tar档案:tar c --files-from=links >links.tar

解压缩tar档案:tar x --files-from=links <links.tar 由于现在启用了本机符号链接,因此tar会用本机符号链接覆盖旧的Cygwin符号链接。

清理:rm -f links links.tar

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


虽然这个方法可以工作(首先我们需要 editrights -u $USER -a SeCreateSymbolicLinkPrivilege),但是这种符号链接并不完全与 mklink 创建的符号链接相同。基本上,CMD 的 mklink 不尊重该权限设置,并且 CMD 的 mklink 正确地将文件类型设置为“.symlink”,而 winln 则没有这样做。其效果基本上是,当使用 Windows Explorer 和 Cygwin 的 ls 渲染时,符号链接实际上看起来像符号链接,当使用 mklink 时,它们知道它是一个 Windows 符号链接。 - CMCDragonkai
你是在谈论winln还是由tar创建的符号链接,使用CYGWIN=winsymlinks:nativestrict。我并没有真正使用过winln,所以无法评论,但在后一种情况下,Cygwin创建的符号链接看起来像资源管理器等中的符号链接。 - Gene Pavlovsky
我在谈论winln。刚刚试过了一下。以前对我来说,CYGWIN=winsymlinks:nativestrict根本不起作用。 - CMCDragonkai
好的,我刚刚尝试了 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 对您是否有效?如果无效,您如何定义该变量? - Gene Pavlovsky
在Windows 10上,启用“开发人员设置”中的“开发人员模式”,以便在非提升的 shell 中创建本机 NTFS 符号链接。参考:https://blogs.windows.com/windowsdeveloper/2016/12/02/symlinks-windows-10/ - Gene Pavlovsky

4

由于 @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上,如果您决定移动符号链接或移动目标文件或同时移动两者,则这两者会有不同的行为。


不错的选择 :-) 请提供您已经测试过脚本的Windows版本(以及可能的Cygwin/MinGW),以帮助其他SO读者。谢谢 ;-) - oHo
3
cygutils-extra 包含一个 winln 命令,该命令提供类似于 ln 的语法,用于创建Windows本地链接。 - Gene Pavlovsky
啊,那个工具很棒。它甚至建议:editrights -a SeCreateSymbolicLinkPrivilege -a $YOUR_USER - CMCDragonkai
2
但实际上应该是 editrights -u $USER -a SeCreateSymbolicLinkPrivilege - CMCDragonkai
因为我是管理员,所以他没有向我建议。 - Gene Pavlovsky
显示剩余2条评论

0

我想最简单的方法是:

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

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

  3. 获利


-5

你可能正在寻找一种使用MSYS在目录树中导航到另一个目的地的方法。确实有一种方法。你应该创建一个包含以下代码的Shell脚本("*.sh"文件):

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

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接