
Estou chamando o bash do cmd.exe assim
c:\cygwin\bin\bash --login -c "echo ф"
e entre no Cygwin 2.8.0
/usr/bin/bash: echo ф: command not found
Ele trata o parâmetro como parte do nome do comando. Fazendo o mesmo no Cygwin 2.5.2, recebo a saída ф
.
Responder1
Como isso costumava funcionar e funciona bem para pessoas executando o bash no Unices (testei no Debian aqui), acho que você encontrou um bug do Cygwin. O projeto Cygwin tem uma página sobrerelatando bugs do Cygwin. Eles têm um monte de informações e etapas úteis, longas demais para serem resumidas aqui.
Enquanto isso, suspeito que você possa contornar isso escapando do personagem. O Bash echo
, quando recebe o -e
sinalizador, interpreta várias sequências de escape:
c:\cygwin\bin\bash --login -c "echo -e '\xd1\x84'"
Deveria trabalhar. Hexadecimal D1 84
é a codificação UTF-8 de ф. Se você tiver a unicode
ferramenta, ela lhe dirá - mas também apenas ecoará o caractere para od
ou xxd
:
$ echo -n 'ф' | od -t x1
0000000 d1 84
0000002
$ echo -n 'ф' | xxd -p
d184
O FAQ do Cygwin me diz que ele usa UTF-8 por padrão, então isso deve funcionar. Mas é claro que você também pode usar outras codificações (achoO Windows usa principalmente UTF16le):
$ echo -n 'ф' | iconv -t utf16le | xxd -p
4404
Responder2
Isso acontece porque cmd.exe
adiciona um par adicional de aspas em torno de argumentos com caracteres não ASCII. Então o que realmente chega na aplicação cygwin é o seguinte:
C:\cygwin\bin\bash --login -c "echo blo"
arg0: /usr/bin/bash
arg1: --login
arg2: -c
arg3: echo blo
Então o bash pode interpretar ' echo blo
', mas:
C:\cygwin\bin\bash --login -c "echo blöd"
arg0: /usr/bin/bash
arg1: --login
arg2: -c
arg3: "echo blöd"
Agora o bash não reconhece ' "echo blöd"
'.
Responder3
A análise do user1274247 é a correta.
Portanto, precisamos encontrar uma maneira de eliminar as aspas iniciais e finais, quando cmd.exe as duplica sem nosso conhecimento.
Eu estava tendo exatamente o mesmo problema ao lidar com caminhos contendo espaços, aspas simples e caracteres não ASCII. Eu resolvi isso separando o comando bash para executar (também conhecido como -c
) e o parâmetro de string problemático.
De acordo com bash man:
-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.
Nosso comando, portanto, torna-se:
C:\cygwin\bin\bash.exe -lc 'a="${0%\"}"; a="${a#\"}";echo "$a"; sleep 10' "C:\spa ces\quo'tes\nonàscîï"
Ou, se preferir usar o terminal mintty:
C:\cygwin\bin\mintty.exe /bin/bash -lc 'a="${0%\"}"; a="${a#\"}";echo "$a"; sleep 10' "C:\spa ces\quo'tes\nonàscîï"
E se você quiser usá-lo no regedit (para iniciar um comando bash ao clicar com o botão direito em um arquivo), aqui está o escape adequado (para aspas e%):
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\""
Estou usando, por exemplo, para duplicar arquivos (extrair de uma caixa de ferramentas maior):
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\" "