No ascii en la línea de comando bash de Cygwin causa error

No ascii en la línea de comando bash de Cygwin causa error

Estoy llamando a bash desde cmd.exe así

c:\cygwin\bin\bash --login -c "echo ф"

y sube a Cygwin 2.8.0

/usr/bin/bash: echo ф: command not found

Trata el parámetro como parte del nombre del comando. Haciendo lo mismo en Cygwin 2.5.2 obtengo el resultado ф.

Respuesta1

Dado que esto solía funcionar y funciona bien para las personas que ejecutan bash en Unices (lo probé en Debian aquí), creo que encontró un error de Cygwin. El proyecto Cygwin tiene una página sobrereportando errores de Cygwin. Tienen un montón de información útil y pasos allí, demasiado largos para resumirlos aquí.

Mientras tanto, sospecho que puedes solucionar este problema escapando del personaje. Bash echo, cuando se le da la -ebandera, interpreta varias secuencias de escape:

c:\cygwin\bin\bash --login -c "echo -e '\xd1\x84'"

Deberia trabajar. Hexadecimal D1 84es la codificación UTF-8 de ф. Si tienes la unicodeherramienta, te lo dirá, pero también lo hará simplemente repetir el carácter en odo xxd:

$ echo -n 'ф' | od -t x1
0000000 d1 84
0000002

$ echo -n 'ф' | xxd -p
d184

Las preguntas frecuentes de Cygwin me dicen que usa UTF-8 de forma predeterminada, por lo que debería funcionar. Pero, por supuesto, también puedes usar otras codificaciones (creoWindows usa principalmente UTF16le):

$ echo -n 'ф' | iconv -t utf16le | xxd -p
4404

Respuesta2

Esto sucede porque cmd.exeagrega un par adicional de comillas alrededor de los argumentos con caracteres que no son ASCII. Entonces lo que realmente llega a la aplicación cygwin es lo siguiente:

C:\cygwin\bin\bash --login -c "echo blo"
arg0: /usr/bin/bash
arg1: --login
arg2: -c
arg3: echo blo

Entonces bash puede interpretar ' echo blo', pero:

C:\cygwin\bin\bash --login -c "echo blöd"
arg0: /usr/bin/bash
arg1: --login
arg2: -c
arg3: "echo blöd"

Ahora bash no reconoce ' "echo blöd"'.

Respuesta3

El análisis del usuario1274247 es el correcto.

Por lo tanto, necesitamos encontrar una manera de eliminar las comillas iniciales y finales, cuando cmd.exe las duplica sin que lo sepamos.

Estaba teniendo exactamente el mismo problema al tratar con rutas que contienen espacios, comillas simples y caracteres que no son ASCII. Lo resolví separando el comando bash a ejecutar (también conocido como -c) y el parámetro de cadena problemático.

Según el hombre bash:

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

Por lo tanto, nuestro comando se convierte en:

C:\cygwin\bin\bash.exe -lc 'a="${0%\"}"; a="${a#\"}";echo "$a"; sleep 10' "C:\spa ces\quo'tes\nonàscîï"

O, si prefieres usar la 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îï"

Y si quieres usarlo en regedit (para iniciar un comando bash al hacer clic derecho en un archivo), aquí tienes el escape adecuado (para comillas y %):

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\""

Lo estoy usando, por ejemplo, para duplicar archivos (extraerlos de una caja de herramientas más grande):

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\" "

información relacionada