Не-ASCII в командной строке Cygwin bash вызывает ошибку

Не-ASCII в командной строке Cygwin bash вызывает ошибку

Я вызываю 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\" "

Связанный контент