msys path conversion (or cygpath for msys?)

社会主义新天地 提交于 2019-11-26 15:47:47

问题


I need to pass /DEF:c:\filepath\myLib.def" command line option from a bash script to MS compiler/linker. The path is generated as part of build process by a bash script. Basically, the argument that my script passes is:

-DEF:/c/filepath/myLib.def

MSYS path conversion can't handle it properly because it doesn't understand /DEF: part. It works if I do

-DEF=/c/filepath/myLib.def

but then ms tools don't understand this parameter. In short, what's the proper way to write that parameter in MSYS bash so that it converts it to proper argument?

On cygwin I could use cygpath, but there is no equivalent, because somebody from msys thinks that it's not needed (even if there are scripts for cygwin that uses cygpath).


回答1:


Update (Aug-2016):

This question is no longer relevant, as msys2 now comes with cygpath in its installation.

...

I'll summarize my research here.

The cygpath equivalent in MSYS is to use this command:

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

The problem with this approach is that it requires existing path, e.g. the c:\some\path has to be an existing directory; however, real cygpath supports paths that do not exist.

So, if you need to get path to a directory that doesn't exist, then you can fallback to sed conversion of the path:

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

The mouthful of slashes is there to satisfy quoting rules of sed. So, if c:\some\path doesn't exist on your PC, it will try to convert forward to back slashes and replace /c/ with c:\ (or any other drive letter). The only drawback for this is that it won't work correctly non-existing paths that contain a mounted component, such as /bin/does-not-exist or /usr/bin/does-not-exist.

One more approach is to use cygpath from cygwin in MSYS. It seems that cygwin sets global environment variable CYGPATH, that is, you can use it from regular cmd.exe:

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

or from MSYS:

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

as long as you set to point /c to /cygdrive/c in cygwin. But this approach will print you /usr located in cygwin installation, not in MSYS.

In short, I think msys should really include real cygpath in the default set of tools just for some cases that aren't handled automatically by msys command line argument conversion logic




回答2:


use pwd -W

or download cygpath for msys from here http://mingw.5.n7.nabble.com/enhanced-version-of-cygpath-td28556.html

and use cygpath -wa




回答3:


Similar to dmitri-rubinstein@ above, I've cleaned up the code a bit and added the reverse conversion as well.

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/'
}



回答4:


I am using this with 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:


My bash foo is weak and I couldn't get regexes working in bash 3.1 so I hacked out a perl script for it:

#!/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);



回答6:


MSYS cygpath

Program

This program convert a DOS path to a UNIX path and vice versa

#!/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);

Compared to Cygwin cygpath

The output from this program is better than the output from Cygwin cygpath in MSYS because

  • Cygwin cygpath remove the Cygwin home from a converted path, f.e.
cygpath "$CYGWIN/usr/local/bin"
/usr/local/bin

which is a problem because

  • it's sometimes useful to convert a DOS Cygwin path to a UNIX path for the purpose of copying files from Cygwin to MSYS

This program doesn't remove the Cygwin home

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

Compared to automatic MSYS path conversion

Manual path conversion has a use in MSYS because

  • the automatic path conversion is inadequate

for f.e.

  • devkitPro make



回答7:


How about this one ? cmd //c echo <your path>

It may not work always but it is the shortest I found



来源:https://stackoverflow.com/questions/12015348/msys-path-conversion-or-cygpath-for-msys

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!