89

当我尝试从 Git Bash shell 创建符号链接时,它每次都失败:

$ ln -s /c/Users/bzisad0/Work testlink
ln: creating symbolic link `testlink' to `/c/Users/bzisad0/Work': Permission denied

除了给出错误消息之外,它唯一做的就是创建一个名为 (在这种情况下) 的空目录testlink

ln我认为可执行文件没有任何问题。例如,它归我所有并标记为可执行文件:

$ which ln
/bin/ln

$ ls -hal /bin/ln
-rwxr-xr-x    1 BZISAD0  Administ      71k Sep  5 11:55 /bin/ln

我还拥有当前目录(~,即/c/Users/bzisad0):

$ ls -dhal .
drwxr-xr-x  115 BZISAD0  Administ      40k Sep  5 12:23 .

我有管理权限,我尝试使用“以管理员身份运行”打开 Git Bash shell,但这没有什么区别。

我尝试打开 Windows 属性ln.exe并将权限级别设置为“以管理员身份运行此程序”,但这无济于事。

我已经进入 Windows 中的 Security -> Advanced 属性,并让自己(而不是管理员组)成为所有者,但这也不能解决任何问题。

我不知所措。我不知道这个错误消息最终是来自ln、来自 Bash 还是来自 Windows,或者我怎么可能缺乏权限。我怎样才能找到这件事的底部?

4

9 回答 9

77

在 MSYSGIT 中创建符号链接是可能的,尽管非常尴尬。

首先,我们需要确保我们在 Windows 上。这是一个用于检查的示例函数:

windows() { [[ -n "$WINDIR" ]]; }

现在,我们不能这样做cmd /C,因为 MSYSGIT 会与这个参数通奸并将其变成C:. 另外,不要试图使用/K,它只有在你没有K:驱动器的情况下才有效。

因此,虽然它会在程序参数上替换这个值,但不会在 heredocs 上。我们可以利用这一点:

if windows; then
    cmd <<< "mklink /D \"${link%/}\" \"${target%/}\"" > /dev/null
else
    ln -s "$target" "$link"
fi

另外:请注意,我包括在内/D是因为我只对目录符号链接感兴趣;Windows 有这样的区别。通过大量的努力,您可以编写一个ln() { ... }包装 Windows API 并用作完整的嵌入式解决方案的函数,但这...留给读者作为练习。


编辑:作为对接受的答案的感谢,这里有一个更全面的功能。

# We still need this.
windows() { [[ -n "$WINDIR" ]]; }

# Cross-platform symlink function. With one parameter, it will check
# whether the parameter is a symlink. With two parameters, it will create
# a symlink to a file or directory, with syntax: link $linkname $target
link() {
    if [[ -z "$2" ]]; then
        # Link-checking mode.
        if windows; then
            fsutil reparsepoint query "$1" > /dev/null
        else
            [[ -h "$1" ]]
        fi
    else
        # Link-creation mode.
        if windows; then
            # Windows needs to be told if it's a directory or not. Infer that.
            # Also: note that we convert `/` to `\`. In this case it's necessary.
            if [[ -d "$2" ]]; then
                cmd <<< "mklink /D \"$1\" \"${2//\//\\}\"" > /dev/null
            else
                cmd <<< "mklink \"$1\" \"${2//\//\\}\"" > /dev/null
            fi
        else
            # You know what? I think ln's parameters are backwards.
            ln -s "$2" "$1"
        fi
    fi
}

还要注意几点:

  1. 我刚刚写了这篇文章,并在 Win7 和 Ubuntu 上对其进行了简要测试,如果你是 2015 年并使用 Windows 9,请先尝试一下。
  2. NTFS 具有重解析点和连接点。我选择了重解析点,因为它更像是一个实际的符号链接并且适用于文件或目录,但连接点将具有在 XP 中成为可用解决方案的好处,除了它仅适用于目录。
  3. 某些文件系统,尤其是 FAT 文件系统,不支持符号链接。现代 Windows 版本不再支持从它们启动,但 Windows 和 Linux 可以挂载它们。

奖励功能:删除链接。

# Remove a link, cross-platform.
rmlink() {
    if windows; then
        # Again, Windows needs to be told if it's a file or directory.
        if [[ -d "$1" ]]; then
            rmdir "$1";
        else
            rm "$1"
        fi
    else
        rm "$1"
    fi
}
于 2014-08-19T23:56:18.563 回答
66

对于我的设置,即安装在 Windows 8.1export MSYS=winsymlinks:nativestrict上的适用于 Windows 2.11.0 的 Git 可以做到这一点,如下所述:https ://github.com/git-for-windows/git/pull/156 启动 Git Bash shell 很重要作为管理员,在 Windows 上只有管理员可以创建符号链接。因此,为了tar -xf工作并创建所需的符号链接:

  1. 以管理员身份运行 Git Bash shell
  2. export MSYS=winsymlinks:nativestrict
  3. 运行焦油
于 2016-12-01T15:19:48.210 回答
29

一种解决方法是mklink从 Bash 运行。这也允许您创建Symlink 或 Junction

注意将mklink命令作为单个参数发送到cmd...

cmd  /c "mklink link target"

这是mklink...的选项

$ cmd /c mklink
   Creates a symbolic link.

MKLINK [[/D] | [/H] | [/J]] Link Target

    /D      Creates a directory symbolic link.  Default is a file
            symbolic link.
    /H      Creates a hard link instead of a symbolic link.
    /J      Creates a Directory Junction.
    Link    specifies the new symbolic link name.
    Target  specifies the path (relative or absolute) that the new link
            refers to.

如果您想改为通过 GUI 创建链接……我推荐Link Shell Extension,它是一个 Windows 资源管理器插件,用于创建符号链接、硬链接、连接点和卷挂载点。我已经用了很多年了!

如果您的系统 C: 驱动器上有一个较小的 SSD 驱动器,并且需要将一些不需要位于 SSD 上的臃肿文件夹符号链接到其他驱动器上,则符号链接可以成为救命稻草。我使用免费的WinDirStat来查找磁盘空间占用。

于 2014-06-30T03:07:50.060 回答
16

我相信lnmsysGit 附带的只是试图复制它的参数,而不是摆弄链接。这是因为链接只在 NTFS 文件系统上工作(某种程度),而 MSYS 团队不想重新实现 ln。

例如,参见http://mingw.5.n7.nabble.com/symbolic-link-to-My-Documents-in-MSYS-td28492.html

于 2013-10-23T19:27:45.750 回答
7

授予自己权限以创建符号链接

  1. 搜索local security policies
  2. Local Policies/User Rights Assignment/Create symbolic links
  3. 花点时间骂Windows。“糟糕的操作系统!糟糕!”
  4. 利润

这授予您创建符号链接的特权。请注意,这将在下次登录时生效。

下一步是弄清楚如何ln配置

env | grep MSYS

我们正在寻找的是MSYS=winsymlink:控制如何ln创建符号链接的方法。

如果变量不存在,则创建它。请注意,这将覆盖现有的 MSYS 环境变量。

setx MSYS winsymlinks:nativestrict

不要

以管理员身份运行 shell 只是为了创建符号链接。

解释

这个错误有点不言自明,但难以捉摸。

您缺乏运行该命令的适当权限。

为什么?

默认情况下,Windows 仅授予管理员符号链接创建权限?

CYGWIN必须做一件事来绕过 Windows 对符号链接的低级处理。

为什么?

某事,某事“安全”

¯\_(ツ)_/¯

编辑:

我刚刚意识到 OP 有管理员权限。我留下这个答案,希望它对其他人有用。

于 2021-06-04T09:25:52.063 回答
4

根据需要扩展 Camilo Martin 的 anwser 以使用 Windows 10 的 /j 参数开关;否则调用只会返回“您没有足够的权限来执行此操作”。

这适用于没有管理员权限的 git bash 2.20.1.windows.1/MINGW64 (Windows 10)(如果您可以同时读/写 /old/path 和 /link/path:

original_folder=$(cygpath -w "/old/path")
create_link_new_folder=$(cygpath -w "/link/path")
cmd <<< "mklink /j \"${create_link_new_folder}\" \"${original_folder}\"" > /dev/null
于 2019-05-13T18:03:42.733 回答
3

对于任何对如何在 Windows 10 Git Bash 2.28.0.0.1 中完成此操作感兴趣的人,您必须在ln -s命令前加上前缀MSYS=..而不是先执行export MSYS=..,即它只是一个命令:

 MSYS=winsymlinks:nativestrict ln -s <TARGET> <NEW_LINK_NAME>
于 2020-11-15T13:10:15.793 回答
2

由于这是在 Msys 或 git bash 中搜索创建符号链接时出现的最热门链接之一,我发现答案是 set MSYS=winsymlinks:native在调用时添加git-cmd.exe(我运行 ConEmu)或取消注释msys2_shell.bat

于 2016-04-08T23:03:03.137 回答
1

我更喜欢 Powershell 而不是 CMD,并认为我会分享这个的 powershell 版本。

在我的例子中,它包括将 ~/.$file 链接到 ~/dotfiles/$file 的符号链接,用于点文件配置。我把它放在一个.sh脚本中并用 git-bash 运行它:

powershell New-Item -ItemType SymbolicLink\
    -Path \$Home/.$file\
    -Target \$Home/dotfiles/$file
于 2019-01-08T08:12:16.373 回答