Git Bash Shell无法创建符号链接


76

当我尝试从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,但这没有什么区别。

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

我进入Windows中的“安全性”->“高级”属性,并让自己(而不是“管理员”组)成为所有者,但是那也不能解决任何问题。

我很茫然。我不知道此错误消息最终是来自ln,来自Bash还是来自Windows,或者我怎么可能缺少权限。我该怎么做?

Answers:


72

尽管很尴尬,但可以在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
}

3
的参数ln并没有真正倒退,因为它支持多个参数,您只需列出一堆文件和一个目录作为目标即可使用:)此外,按常规顺序,它类似于cp并且mv不易混淆。
Wolph

2
@Wolph看,我没有尝试创建“嵌入式”解决方案真是太好了,哈哈。我不知道您可以通过两条以上的路径ln
卡米洛·马丁

2
嘿,这是一个非常好的答案,感觉就像在挑剔,但是...为什么您必须去颠倒参数顺序?相反,它是“链接目标链接名”。请 (编辑:好的,我意识到这是因为您希望单参数重载让它检查链接名称是否为链接,而unixln则不这样做。指向仍然站立。)
史蒂芬·卢

2
我来自未来,但我忘了购买Windows 9。
格雷格,

6
我在2019年,仍然没有Windows 9 :)
Maxim Mazurok,

46

对于我的设置,这就是在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. 运行焦油

1
这是真正的答案
〜– fatfatson

5
如果您打开Windows Developer模式(需要Windows 10版本1703或更高版本),则无需以管理员身份运行docs.microsoft.com/zh-cn/windows/uwp/get-started/…–
Sebastian

ln -s currentFile newLink也可以使用这种方法(不仅限于tar)。创建的链接在Windows资源管理器中显示为快捷方式,但是跟随该快捷方式不会跳转到其他文件夹的路径,而是会看到类似的路径C:\currentFolder\newLink。我以前从未见过这样的Windows链接!
乔西亚·约德

我在这里开发了一个包含示例和图像的示例:stackoverflow.com/a/63325536/1315009-也从那里反向链接到这里。
哈维·蒙特罗

25

一种解决方法是mklink从Bash运行。这也使您可以创建符号链接或连接点

注意将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上的一些肿的文件夹符号链接到其他驱动器上,则Symlinks可以节省生命。我使用免费的WinDirStat来查找磁盘空间。


2
足够普遍的是,MSYSGIT设法使其无法运行,从而进一步使用户鸡奸,cmd /c因为/c它总是会被替换成C:(它的文件系统使用/c/Windows/...约定)。echo -n | cmd /k ...如果没有K:驱动器,您可以做的幸运的事情。辉煌。
卡米洛·马丁

2
除了出于安全原因需要Windows管理员的事实之外,人们还有其他原因为什么会说“ Windows对符号链接的支持不佳”吗?您可以授予用户使用secpol.msc创建未提升的符号链接的权限。
贾斯汀·邓拉普

2
@JustinDunlap早期在Windows NT / 2000中进行链接的实现效果很差,并且看起来像是经过深思熟虑的“ hack”(Vista / Win7 / 8实现对此进行了清理)。大多数Windows开发人员/系统管理员都不习惯使用它们,MS文档几乎从未引用它们。因此,许多Windows开发人员不会在软件解决方案中考虑它们!我怀疑产品供应商尚未考虑许多与链接有关的安全方案,因此MS将其设置为“仅管理员”。在Linux / OSX / Unix上,它们是主流/受鼓励的,因此大多数应用程序都经过了很好的测试,并有望与它们一起使用。
Tony O'Hagan 2014年

6
/c可以这样转义@CamiloMartin//c以获得powershell命令而不是C:驱动器。我还想添加一些示例,以准确了解mklink在git bash shell中使用什么样的语法,因为花了我一段时间才弄清楚。正如Tony所述,引用整个mmklink命令将可以正常工作,例如:cmd //c "mklink .\b_dir\test.txt .\a_dir\test.txt",或者您可以省略引号并避免这样的后退:cmd //c mklink .\\b_dir\\test.txt .\\a_dir\\test.txt
Grant Humphries

1
@GrantHumphries太好了,不知道//c。顺便说一句,对于像这样的情况,单引号通常更方便,因为在这些字符串中没有进行解析。
卡米洛·马丁

16

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

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


3
你是对的。当我尝试执行操作时ln file1 file2; ln file1 file3; ln file1 file4,得到的输出似乎是有效的链接计数ls -l。但是请注意,ln: hard link not allowed for directory.如果尝试这样做会失败。
奥斯汀·黑斯廷斯

1
大多数现代Windows系统都没有NTFS吗?另外,自从1993年Windows NT 3.1以来,他们还没有拥有它们(根据可信赖的旧维基百科)?
trysis

2
是的,这似乎是一个明显的遗漏,没有人可以责怪微软。
iconoclast 2014年

1
@ AustinHastings,Linux也不允许在目录上进行硬链接,因此该部分仍与保持一致ln
trysis

1
@AustinHastings不,不真正支持FAT 。您无法再在FAT上安装当前支持的Windows版本。
卡米洛·马丁

2

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


1
我试了一下,msys仍然复制并且没有创建实际的链接-我在Win10
0fnt,2016年

@sweelim请说明git-cmd.exe您在使用哪个功能。
clacke

我只是尝试设置MSYS2=winsymlinks:nativeMSYS=winsymlinks:native并且CYGWIN=winsymlinks:native使用了官方的Git Windows发行版2.8.3.windows.1ln -s没有符号链接,而是递归复制。
clacke

2

需要扩展适用于Windows 10的/ j参数开关时,扩展Camilo Martin的anwser;否则,呼叫将仅返回“您没有足够的权限执行此操作”。

这适用于没有管理员权限的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

1

我更喜欢Powershell而不是CMD,并认为我会分享此功能的Powershell版本。

就我而言,它包括将〜/.$ file链接到〜/ dotfiles / $ file的符号链接,以进行点文件配置。我将其放在.sh脚本中并使用git-bash运行:

powershell New-Item -ItemType SymbolicLink\
    -Path \$Home/.$file\
    -Target \$Home/dotfiles/$file

0

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

 MSYS=winsymlinks:nativestrict ln -s <TARGET> <NEW_LINK_NAME>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.