Msys (или cygpath для msys?)

Мне нужно передать /DEF:c:\filepath\myLib.def "из командной строки из bash script в компилятор/компоновщик MS. Путь создается как часть процесса сборки с помощью bash script. В принципе, аргумент, который проходит мой script:

-DEF:/c/filepath/myLib.def
Преобразование пути

msys не может обрабатывать его должным образом, потому что оно не понимает часть /DEF:. Он работает, если я делаю

-DEF=/c/filepath/myLib.def

но тогда инструменты ms не понимают этот параметр. Короче говоря, какой правильный способ записать этот параметр в MSYS bash, чтобы он преобразовал его в правильный аргумент?

В cygwin я могу использовать cygpath, но нет эквивалента, потому что кто-то из msys считает, что он не нужен (даже если есть скрипты для cygwin, который использует cygpath).

Ответы

Ответ 1

Обновление (август-2016):

Этот вопрос больше не уместен, поскольку msys2 теперь поставляется с cygpath в своей установке.

...

Вкратце расскажу о моих исследованиях.

эквивалент cygpath в MSYS заключается в использовании этой команды:

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

Проблема с этим подходом заключается в том, что он требует существующего пути, например. c:\some\path должен быть существующим каталогом; однако real 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 существует множество косых черт. Итак, если c:\some\path не существует на вашем ПК, он попытается преобразовать обратную косую черту и заменить /c/ на c:\ (или любую другую букву диска). Единственным недостатком этого является то, что он не будет корректно работать с несуществующими путями, которые содержат смонтированный компонент, например /bin/does-not-exist или /usr/bin/does-not-exist.

Еще один подход - использовать cygpath из cygwin в MSYS. Кажется, что cygwin устанавливает глобальную переменную среды CYGPATH, то есть вы можете использовать ее из обычного cmd.exe:

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

или из MSYS:

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

пока вы установите для пункта /c в /cygdrive/c в cygwin. Но этот подход напечатает вас /usr, расположенный в установке cygwin, а не в MSYS.

Короче говоря, я думаю, что msys действительно должен включать реальный cygpath в набор инструментов по умолчанию только для некоторых случаев, которые автоматически не обрабатываются логикой преобразования аргументов командной строки msys

Ответ 2

Я использую это с помощью msysgit:

winpath() {
    if [ -z "$1" ]; then
        echo "[email protected]"
    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
}

Ответ 4

Как и 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/'
}

Ответ 5

Мой bash foo слаб, и я не мог получить регулярные выражения, работающие в bash 3.1, поэтому я взломал perl script для него:

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

Программа

Эта программа преобразует путь 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

Выход из этой программы лучше, чем выход из Cygwin cygpath в MSYS, потому что

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

Ответ 7

Как насчет этого? cmd //c echo <your path>

Он может работать не всегда, но это самый короткий найденный