在 msys 中使用 mklink

在 msys 中使用 mklink

我知道 Vista 之后的 Windows 提供了mklinkshell 命令。我想从 Msys 终端使用它。有什么想法吗?

当我mklink在 msys 终端上输入时,它输出sh: mklink: command not found。Msys 只提供了一个虚假的ln实用程序,它看起来与 实际上相同cp

我尝试编写一个 shell 脚本来打开 Windows shell 并mklink在其中运行,但是当我的 shell 脚本尝试执行时cmd /C <instructions>,msys 会将 Windows shell 带到当前终端的前台并将其留在那里,而不运行指令。

答案1

Windows 10 现在支持符号链接,无需以管理员身份运行,只要您在 Windows 设置中打开开发人员模式。

一旦完成后,您就可以使用主目录中的文件ln中一行来正常工作!.bashrc

export MSYS=winsymlinks:nativestrict

(我无法弄清楚 Git Bash 安装中等效的 .ini 文件在哪里。但在那里设置环境变量可能也有效。)

Josh Kelley 的这篇非常有用的文章中有更多详细信息: https://www.joshkel.com/2018/01/18/symlinks-in-windows/

答案2

cmd //c mklink直接在 MSYS bash 命令行上使用就可以了。

$ 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.

注意:mklink 命令和参数需要作为 cmd 的单个参数提供。像这样引用整个命令

cmd //c 'mklink link target'

请注意,命令通常是

cmd /c 'mklink链接目标

这可以在 Cygwin 和其他 shell 环境中工作,甚至可以在现有的 CMD 会话中工作。但是,msys 似乎会破坏命令行参数(对于 Windows 命令),它会将其解释/c为磁盘根目录的路径名C,并将其转换为c:\。输入//c已发现会导致 msys 将/c选项传递给cmd。请参阅如何从 msys shell 运行内部 cmd 命令?

答案3

您可以使用 Windows 原生符号链接。要启用它,请取消注释以下行:

MSYS=winsymlinks:nativestrict

在 MSYS2 中启动 bat 文件。并以管理员权限运行 MSYS2。

答案4

MSYS=winsymlinks:nativestrict要求您以提升模式运行 MSYS2,我对此确实感到不舒服。

此脚本仅在调用时提示 UAC 提升,当然它对于脚本编写来说没有用,但至少它满足我的需要:

  • 〜/脚本/sh/msys2-ln.sh:

    #!/bin/sh
    if [ "$#" -eq 2 -a "$1" == "-s" ]; then
        TARGET="$2"
        LINK=$(basename "$TARGET")
    elif [ "$#" -eq 3 -a "$1" == "-s" ]; then
        TARGET="$2"
        LINK="$3"
    else
        echo "this weak implementation only supports \`ln -s\`"
        exit
    fi
    
    if [ -d "$TARGET" ]; then
        MKLINK_OPTS="//d"
    fi
    
    TARGET=$(cygpath -w -a "$TARGET")
    LINK=$(cygpath -w -a "$LINK")
    
    echo "$TARGET"
    echo "$LINK"
    cscript //nologo ~/scripts/wsh/run-elevated.js \
        cmd //c mklink $MKLINK_OPTS "$LINK" "$TARGET"
    
  • 〜/脚本/ wsh /运行-elevated.js

    var args = WScript.Arguments;
    if(args.length == 0){
        WScript.Echo("nothing to run");
        WScript.Quit(0);
    }
    
    var quoted_args = [];
    for(var i = 1; i < args.length; ++i){
        var arg = args(i); // it's a callable, not array like
        if(arg.indexOf(" ") != -1){
            arg = "\"" + arg + "\"";
        }
        quoted_args.push(arg);
    }
    
    var SHAPP = WScript.CreateObject("shell.application");
    SHAPP.ShellExecute(args(0), quoted_args.join(" "), "", "runas", 1);
    
  • ~/.bashrc

    # workaround for MSYS2's awkward ln
    if [ $- == *i* -a ! -z $MSYSTEM ]; then
        alias ln='~/scripts/sh/msys2-ln.sh'
        alias ecmd='powershell "start-process cmd.exe \"/k cd /d $(pwd -W)\" -verb runas"'
    fi
    

附加的 ecmd 别名在当前目录中启动提升的 cmd,有时可能会有用,它也可以作为通过 powershell 获取 UAC 提升的示例,如果有人知道如何正确摆脱这个问题,我们就可以抛弃那个 WSH 助手。

相关内容