【问题标题】:msys path conversion (or cygpath for msys?)msys 路径转换(或 msys 的 cygpath?)
【发布时间】:2012-08-14 11:11:23
【问题描述】:

我需要将 /DEF:c:\filepath\myLib.def" 命令行选项从 bash 脚本传递给 MS 编译器/链接器。路径是由 bash 脚本作为构建过程的一部分生成的。基本上,参数我的脚本通过的是:

-DEF:/c/filepath/myLib.def

MSYS path conversion 无法正确处理它,因为它不理解 /DEF: 部分。如果我这样做,它会起作用

-DEF=/c/filepath/myLib.def

但是ms工具不理解这个参数。简而言之,在 MSYS bash 中写入该参数以便将其转换为正确参数的正确方法是什么?

在 cygwin 上我可以使用 cygpath,但没有等效的,因为来自 msys 的人认为不需要它(即使有使用 cygpath 的 cygwin 脚本)。

【问题讨论】:

  • “不需要”的论点可以延伸很长的路要走。但有时它很有用,例如 Jython 的 shell 脚本允许 Cygwin 但不允许 MSYS。 Jython 的 shell 脚本调用 cygpath。如果我们将@user1307996 的答案中的cygpath.exe 添加到MSYS bin 中,它可以工作。
  • 这里处理两个方向:stackoverflow.com/q/13701218/321973
  • @TobiasKienzler 尝试使用这些毛茸茸的脚本将\Windows 转换为posix。在 cygwin 上不使用 cygpath 是没有意义的
  • 当然没有,除非你没有 cygpath 可用...
  • 我投票决定将此问题作为离题结束,因为所描述的问题已在更高版本的软件中得到解决 - msys2 包括 cygpath。

标签: path portability mingw32 msys cygpath


【解决方案1】:

我的 bash foo 很弱,我无法让正则表达式在 bash 3.1 中工作,所以我为它破解了一个 perl 脚本:

#!/bin/env perl
use strict;

my @r;
foreach my $e (@ARGV) {
 $e=~s/\//\\/g;
 $e=~s/^\\([A-Za-z])\\/\1:\\/;
 push @r, $e;
}

print join(" ", @r);

【讨论】:

  • 我知道如何使用脚本来做到这一点;我认为有一些 MSYS 特定的方式来引用参数,以便它自动转换此路径。这就是我要找的。​​span>
【解决方案2】:

更新(2016 年 8 月):

这个问题不再相关,因为msys2 现在在其安装中附带了cygpath

...

我将在这里总结我的研究。

MSYS 中的 cygpath 等效项是使用此命令:

{ cd /c/some/path && pwd -W; } | sed 's|/|\\|g'

这种方法的问题是它需要现有的路径,例如c:\some\path 必须是现有目录;然而,真正的 cygpath 支持不存在的路径。

所以,如果你需要获取一个不存在的目录的路径,那么你可以回退到路径的 sed 转换:

{ cd 2>/dev/null /c/some/path && pwd -W ||
  echo /c/some/path | sed 's|^/\([a-z,A-Z]\)/|\1:/|'; } | sed 's|/|\\|g'

满口的斜线是为了满足sed的引用规则。因此,如果您的 PC 上不存在 c:\some\path,它将尝试将正斜杠转换为反斜杠,并将 /c/ 替换为 c:\(或任何其他驱动器号)。唯一的缺点是它无法正常工作包含已安装组件的不存在路径,例如 /bin/does-not-exist/usr/bin/does-not-exist

另一种方法是在 MSYS 中使用来自 cygwin 的 cygpath。看来cygwin设置了全局环境变量CYGPATH,也就是说,你可以从常规的cmd.exe中使用它:

%CYGPATH% -w /c/some/path
C:\some\path

或来自 MSYS:

$CYGPATH -w /c/some/path
C:\some\path

只要你在 cygwin 中将/c 指向/cygdrive/c。 但是这种方法会打印你 /usr 位于 cygwin 安装中,而不是在 MSYS 中。

简而言之,我认为 msys 确实应该在默认工具集中包含真正的 cygpath,仅用于 msys 命令行参数转换逻辑无法自动处理的某些情况

【讨论】:

  • 如果您已经在使用单引号,则无需转义反斜杠。
  • 很好的答案,但是如果您的 sed 脚本被修改为将 ([a-z]) 更改为 ([a-z,A-Z]) ,那么也可以使用大写驱动器号。
  • 此外,通过删除第一个 sed 脚本末尾的正斜杠,它允许将 /c 之类的内容转换为 C: 而不是 \c。
  • @stellarpower 但随后/abc 也将转换为a:bca:\bc,具体取决于/a 转换为的内容。
  • sed 部分不精确 - pwd -W 生成大写驱动器号,而 sed 保留小写驱动器号(是的,这有时很重要)。
【解决方案3】:

这对我有用

df "$1" | tac >k
read b <k
rm k
set "$1" $b
echo ${1/$7/$2/}

ref

【讨论】:

  • 您是否尝试过我自己的解决方案:sh -c 'cd /c/some/path; pwd -W'?它在功能上等同于 cygwin 上的 cygpath -w '/c/some/path'。您的解决方案可能具有 cygpath 的功能,但尚不清楚如何将其转换为类似 cygpath 的命令。
【解决方案4】:

我将它与 msysgit 一起使用:

winpath() {
    if [ -z "$1" ]; then
        echo "$@"
    else
        if [ -f "$1" ]; then
            local dir=$(dirname "$1")
            local fn=$(basename "$1")
            echo "$(cd "$dir"; echo "$(pwd -W)/$fn")" | sed 's|/|\\|g';
        else
            if [ -d "$1" ]; then
                echo "$(cd "$1"; pwd -W)" | sed 's|/|\\|g';
            else
                echo "$1" | sed 's|^/\(.\)/|\1:\\|g; s|/|\\|g';
            fi
        fi
    fi
}

【讨论】:

    【解决方案5】:

    MSYS cygpath

    程序

    此程序将 DOS 路径转换为 ​​UNIX 路径,反之亦然

    #!/bin/env perl
    # DOS to UNIX path conversion
    # © John S. Peterson. License GNU GPL 3.
    use strict;
    use Getopt::Std;
    
    # usage
    if ($#ARGV == -1) {
        print 'Usage: cygpath (-w) NAME...
    
    Convert Unix and Windows format paths
    
    Output type options:
    
      -w, --windows         print Windows form of NAMEs (C:\WINNT)
    ';
        exit 0;
    }
    
    # option
    my %opt;
    getopts('w', \%opt);
    
    # convert path
    my @r;
    foreach my $e (@ARGV) {
        if ($opt{w}) {
            # add drive letter suffix
            $e =~ s,^\/([A-Za-z])\/,\1:\/,;
            $e =~ s,\/,\\,g;
    
        } else {
            $e =~ s,\\,\/,g;
            # add leading slash
            $e = "/$e";
            # remove drive letter suffix
            $e =~ s,:,,;
        }
    
        push @r, $e;
    }
    
    print join("\n", @r);
    

    与 Cygwin 相比 cygpath

    这个程序的输出比 MSYS 中 Cygwin cygpath 的输出要好,因为

    • Cygwin cygpath 从转换后的路径中删除 Cygwin 主页,f.e.
    cygpath "$CYGWIN/usr/local/bin"
    /usr/local/bin
    

    这是个问题,因为

    • 将 DOS Cygwin 路径转换为 ​​UNIX 路径以将文件从 Cygwin 复制到 MSYS 有时很有用

    此程序不会删除 Cygwin 主页

    cygpath "$CYGWIN/usr/local/bin"
    /c/file/program/cygwin/usr/local/bin
    

    与自动 MSYS 路径转换相比

    手动路径转换在 MSYS 中很有用,因为

    • 自动路径转换不足

    对于 f.e.

    【讨论】:

      【解决方案6】:

      使用pwd -W

      或 从这里下载 msys 的 cygpath http://mingw.5.n7.nabble.com/enhanced-version-of-cygpath-td28556.html

      并使用cygpath -wa

      【讨论】:

      • 和我自己的回答有什么不同?
      • 我提供的指向 cygpath.exe 的链接可能与 cygwin 不同。
      • 提供的链接提供了无法正常工作的 cygpath。例如。 cygpath -w /c/foobar 打印 c:/foobar 而它应该打印 c:\foobar
      【解决方案7】:

      与上面的 dmitri-rubinstein@ 类似,我已经稍微清理了代码并添加了反向转换。

      winpath() {
          if [ ${#} -eq 0 ]; then
              : skip
          elif [ -f "$1" ]; then
              local dirname=$(dirname "$1")
              local basename=$(basename "$1")
              echo "$(cd "$dirname" && pwd -W)/$basename" \
              | sed \
                -e 's|/|\\|g';
          elif [ -d "$1" ]; then
              echo "$(cd "$1" && pwd -W)" \
              | sed \
                -e 's|/|\\|g';
          else
              echo "$1" \
              | sed \
                -e 's|^/\(.\)/|\1:\\|g' \
                -e 's|/|\\|g'
          fi
      }
      
      unixpath() {
          echo "$1" \
          | sed -r \
            -e 's/\\/\//g' \
            -e 's/^([^:]+):/\/\1/'
      }
      

      【讨论】:

        【解决方案8】:

        这个怎么样? cmd //c echo &lt;your path&gt;

        它可能并不总是有效,但它是我发现的最短的

        【讨论】:

        • stackoverflow.com/questions/40257679/…中提供了基于此如何从Makefile中传递它的解决方案
        • 在那里评论说语法实际上可能对我造成了问题,对cmd /c echo ... 稍作更改可能会更好。
        猜你喜欢
        • 2015-08-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多