Cygwin bashコマンドラインのASCII以外の場合にエラーが発生する

Cygwin bashコマンドラインのASCII以外の場合にエラーが発生する

cmd.exeでbashをこのように呼び出します。

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

Cygwin 2.8.0を入手

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

引数をコマンド名の一部として扱います。 Cygwin 2.5.2で同じことをすると、出力が表示されますф

答え1

これは以前はうまくいき、Unicesでbashを実行している人にとってはうまくいったので(ここでDebianでテストしました)、Cygwinのバグを見つけたようです。 Cygwinプロジェクトには次のプロジェクトがあります。Cygwinのバグ報告。ここには有用な情報や手順がたくさんあり、ここにまとめるには長すぎます。

これまでキャラクターを脱出すればこの問題を解決できるようです。 Bashは、フラグがecho与えられたときに-e様々なエスケープシーケンスを解釈します。

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

動作する必要があります。 16進数D1 84は、fのUTF-8エンコーディングです。ツールがある場合はunicodeこれを知らせますが、次の文字のみが表示されodますxxd

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

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

Cygwin FAQでは、デフォルトでは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

ユーザー 1274247 の分析が正確です。

したがって、cmd.exeが私たちが知らない間に前後引用符を2倍に増やすときに先行引用符と末尾引用符を削除する方法を見つける必要があります。

スペース、一重引用符、および非ASCII文字を含むパスを処理するときにも同じ問題が発生しました。私は実行するbashコマンド(別名-c)と問題の文字列引数を分離することでこの問題を解決しました。

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. 

したがって、私たちの命令は次のとおりです。

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

関連情報