WSLでWindowsのコマンドが文字化けする場合の対処法


WSLはWindowsのコマンドを直接実行できる

WSLインスタンスで環境変数を見ると、Windowsのアプリケーションディレクトリにパスが通っていることがわかります。

$ echo $PATH
........:/mnt/c/WINDOWS/system32:/mnt/c/WINDOWS:/mnt/c/WINDOWS/System32/Wbem:.....

ただ、通常Windowsだとpowershell, wsl などと .exe を省略できるのですが、WSLからは省略はできません。

$ which wsl

(何も表示されない)

$ which wsl.exe
/mnt/c/WINDOWS/system32/wsl.exe

(wsl.exeが見つかる)

もし、wsl や powershell をよく使う場合には/home/<ユーザー名>/.bashrcに aliasを書いておくと便利です。

alias powershell=powershell.exe
alias wsl=wsl.exe

これで wsl -> wsl.exe とみなされて .exe を省略可能になります。

コマンドの実行結果が文字化けする?

コンソールにもよると思いますが、Windows Terminalでは普通にコマンド実行すると、日本語のメッセージも特に問題なく表示できます。

$ wsl -l
Linux 用 Windows サブシステム ディストリビューション:
Ubuntu (既定)
Alpine

ところが、wsl のヘルプメッセージは長いので less を通してみようとすると見事に文字化けします。

$ wsl --help | less
C^@o^@p^@y^@r^@i^@g^@h^@t^@ ^@(^@c^@)^@ ^@M^@i^@c^@r^@o^@s^@o^@f^@t^@ ^@C^@o^@r^@p^@o^@r^@a^@t^@i
^@o^@n^@.^@ ^@A^@l^@l^@ ^@r^@i^@g^@h^@t^@s^@ ^@r^@e^@s^@e^@r^@v^@e^@d^@.^@^M^@^M^@
^@^M^@^M^@
^@^?O(u<D5>l:^@ ^@w^@s^@l^@.^@e^@x^@e^@ ^@[^@A^@r^@g^@u^@m^@e^@n^@t^@]^@ ^@[^@O^@p^@t^@i^@o^@n^@s
^@.^@.^@.^@]^@ ^@[^@C^@o^@m^@m^@a^@n^@d^@L^@i^@n^@e^@]^@^M^@^M^@
^@^M^@^M^@
^@L^@i^@n^@u^@x^@ ^@<D0>0<A4>0<CA>0<EA>0<92>0<9F>[L<88>Y0<8B>0_0<81>0n0^U_pe:^@^M^@^M^@
^@^M^@^M^@

勘の働く方はこの文字化けパターンをみて気づくかもしれません。^@を取り除くと

C^@o^@p^@y^@r^@i^@g^@h^@t^@ ^@(^@c^@)^@ ^@M^@i^@c^@r^@o^@s^@o^@f^@t^@ ^@C^@o^@r^@p^@o^@r^@a^@t^@i
  ↓    ↓    ↓
Copyright (c) Microsoft Corporati

読めます。ということは、ascii文字も16bit化されているようです。
ということは、これはおそらく UTF-16 です。最近でこそnotepad.exeもUTF-8が使えるようになりましたが、WindowsはUTF-16でしたね。

iconv で文字コードを変換する

ということで

$ wsl -help | iconv -fUTF16LE | less
Copyright (c) Microsoft Corporation. All rights reserved.
使用法: wsl.exe [Argument] [Options...] [CommandLine]
Linux バイナリを実行するための引数:
    コマンドラインを指定しない場合、wsl.exe によって既定のシェルが起動されます。

※UTF16LE は UTF-16 かつリトルエンディアンという意味です。リトル・ビックエンディアンというのはコンピュータの中でのデータの並び順のことですが、CPUによって異なる場合があるので明示的に指定が必要な場合があります。Ubuntuでは utf16, utf-16, utf16le 等で大丈夫でした。

無事読めるようになりました。