2017/03/07

ls の出力が文字化けみたいになってしまう原因

注:
今回は文字コードがらみの話ではありません。日本語が文字化けしてしまう場合は文字コードを確認してみると良いでしょう。

ls の出力をそのままファイルに出力すると、文字化けのようになってしまうことがあります。

$ ls
Dir/
$ ls > ../test.txt
$ less ../test.txt
ESC[0mESC[01;34mDirESC[0m

原因はフォーマットコード

これ、最初に見るとびっくりしますが、実はターミナルのフォーマットコードです。 ls の出力をターミナル上で確認すると、以下のように色付きなのがわかります。

つまり、表示されてはいないけど、ターミナルの装飾用フォーマットコードが同時に出力されているということです。 例えば .bashrc 等の中で alias を設定していたりすると、こういった動作になります。

1
alias ls='ls --color'

ls はわかりやすい例ですが、その他の装飾文字を出力するコマンドは同様の問題が起こる可能性があります。

対策1 フォーマットを切る

当たり前ですが、フォーマットしないように設定すれば直ります。一時的に対策するには良いでしょう。

$ ls --color=never > ../test.txt
$ less ../test.txt
Dir

対策2 --color=auto を指定する

--color--color=always と等価なので問題が起こりますが、 --color=auto にするとターミナルに出力される時だけフォーマットコードが挿入されます。 .bashrc 等の設定で、以下のように --color=auto にしておくと問題が起きにくくなります。

1
alias ls='ls --color=auto'

フォーマットコードの仕様

フォーマットコードは慣れると簡単で、"ESC" (0x1b) "[" (0x5b) と "m" (0x6d) の間にコードを入れて表します。 文字装飾(太字、イタリック等)と文字色、背景色を設定することが出来ます。

具体的な値は以下のサイトにわかりやすくまとまっていたのでご参照ください。

参考

例えば先程の例 ESC[0mESC[01;34mDirESC[0m だと、 以下のようになります。

  • "01" Bold
  • ";" 区切り文字
  • "34" Forground Blue
  • 前後の ESC[0m はリセット

ちなみに、バイナリだと以下のようになります。

$ ls --color | od -t x1
0000000 1b 5b 30 6d 1b 5b 30 31 3b 33 34 6d 44 69 72 1b
0000020 5b 30 6d 0a

0 件のコメント: