
Я вызываю bash из cmd.exe вот так
c:\cygwin\bin\bash --login -c "echo ф"
и получите Cygwin 2.8.0
/usr/bin/bash: echo ф: command not found
Он обрабатывает параметр как часть имени команды. Делая то же самое на Cygwin 2.5.2 я получаю вывод ф
.
решение1
Так как это работало и работает отлично для людей, использующих bash на Unix (я тестировал на Debian здесь), я думаю, что вы нашли ошибку Cygwin. У проекта Cygwin есть страница осообщать об ошибках Cygwin. У них там куча полезной информации и шагов, но слишком много, чтобы пересказывать их здесь.
В то же время, я подозреваю, что вы можете обойти это, экранируя символ. Bash's echo
, когда ему дан -e
флаг, интерпретирует различные последовательности экранирования:
c:\cygwin\bin\bash --login -c "echo -e '\xd1\x84'"
должно работать. Шестнадцатеричное D1 84
— это кодировка UTF-8 ф. Если у вас есть инструмент unicode
, он вам скажет — но то же самое можно сделать и с помощью простого повтора символа в od
или xxd
:
$ echo -n 'ф' | od -t x1
0000000 d1 84
0000002
$ echo -n 'ф' | xxd -p
d184
В FAQ Cygwin мне сказано, что он использует UTF-8 по умолчанию, так что это должно работать. Но, конечно, вы можете использовать и другие кодировки (я думаю,Windows в основном использует UTF16le):
$ echo -n 'ф' | iconv -t utf16le | xxd -p
4404
решение2
Это происходит, потому что cmd.exe
добавляет дополнительную пару кавычек вокруг аргументов с не-ASCII символами. Так что то, что на самом деле приходит в приложение cygwin, это следующее:
C:\cygwin\bin\bash --login -c "echo blo"
arg0: /usr/bin/bash
arg1: --login
arg2: -c
arg3: echo blo
Итак, bash может интерпретировать ' echo blo
', но:
C:\cygwin\bin\bash --login -c "echo blöd"
arg0: /usr/bin/bash
arg1: --login
arg2: -c
arg3: "echo blöd"
Теперь bash не распознает ' "echo blöd"
'.
решение3
Анализ пользователя user1274247 верен.
Поэтому нам нужно найти способ удалить начальные и конечные кавычки, когда cmd.exe удваивает их без нашего ведома.
У меня была точно такая же проблема при работе с путями, содержащими пробелы, одинарные кавычки и не-ASCII символы. Я решил ее, разделив команду bash для выполнения (aka -c
) и проблемный строковый параметр.
По словам Башмана:
-c string
If the -c option is present, then commands are read from string. If there are arguments after the string, they are assigned to the positional parameters, starting with $0.
Поэтому наша команда становится следующей:
C:\cygwin\bin\bash.exe -lc 'a="${0%\"}"; a="${a#\"}";echo "$a"; sleep 10' "C:\spa ces\quo'tes\nonàscîï"
Или, если вы предпочитаете использовать терминал Mintty:
C:\cygwin\bin\mintty.exe /bin/bash -lc 'a="${0%\"}"; a="${a#\"}";echo "$a"; sleep 10' "C:\spa ces\quo'tes\nonàscîï"
А если вы хотите использовать его в regedit (для запуска команды bash при щелчке правой кнопкой мыши по файлу), вот правильное экранирование (для кавычек и %):
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Classes\*\shell\Test]
@="echo filename in bash"
[HKEY_CURRENT_USER\Software\Classes\*\shell\Test\command]
@="C:\\cygwin\\bin\\mintty.exe /bin/bash -lc ' a=\"${0%%\\\"}\"; a=\"${a#\\\"}\";echo \"$a\"; sleep 10 ' \"%1\""
Я использую его, например, для дублирования файлов (выдержка из большего набора инструментов):
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Classes\*\shell\Duplicate]
@="Duplicate file"
[HKEY_CURRENT_USER\Software\Classes\*\shell\Duplicate\command]
@="C:\\cygwin\\bin\\mintty.exe /bin/bash -lc ' a=\"${0%%\\\"}\"; a=\"${a#\\\"}\" ; cd \"$(dirname \"$(cygpath \"$a\")\")\"; f=\"$(basename \"$a\")\" ; n=\"$(basename \"$a\" \".${f##*.}\")\" ; cp \"${f}\" \"${n}-copy.${f##*.}\" ' \"%1\" "