在 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
}
还要注意几点:
- 我刚刚写了这篇文章,并在 Win7 和 Ubuntu 上对其进行了简要测试,如果你是 2015 年并使用 Windows 9,请先尝试一下。
- NTFS 具有重解析点和连接点。我选择了重解析点,因为它更像是一个实际的符号链接并且适用于文件或目录,但连接点将具有在 XP 中成为可用解决方案的好处,除了它仅适用于目录。
- 某些文件系统,尤其是 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
}