【问题标题】:Enable native NTFS symbolic links for Cygwin为 Cygwin 启用本机 NTFS 符号链接
【发布时间】: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 pointNTFS symbolic link

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

【问题讨论】:

    标签: cygwin mingw symlink ntfs ln


    【解决方案1】:

    ⸻⸻⸻ 简答 ⸻⸻⸻

    定义环境变量:

    CYGWIN=winsymlinks:nativestrict
    

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

    ⸻⸻⸻  长答案 ⸻⸻⸻

    默认 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 快捷方式属性,高级 → 以管理员身份运行)。

    特别感谢 GuriaSpooky 的贡献。

    【讨论】:

    • 我刚刚对这个内容丰富的答案投了赞成票。我还添加了一个建议的编辑,即启用了 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】:

    我想最简单的方法是

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

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

    3. 利润

    【讨论】:

      【解决方案5】:

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

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

      【讨论】:

      • 您好 FreeCodeRide。感谢您的想法,但我不确定是否理解。请举个例子。例如,您可以创建一个目标文件,然后创建一个链接到该目标文件的文件……干杯;)
      猜你喜欢
      • 2012-10-03
      • 2011-07-10
      • 2012-02-20
      • 2011-05-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-08
      • 2023-02-14
      相关资源
      最近更新 更多