gitの日本語ファイル名が数字の羅列になるとき(PowerShell)
毎日の変更を自動でコミットするPowerShellのスクリプトを組んでいたときのことです。git status --porcelain の出力からファイルのパスを取り出して、ファイルごとに処理する仕組みにしたところ、日本語の名前のファイルだけ様子がおかしいことに気づきました。
"dir/\346\227\245\346\234\254.csv"
これは「dir/日本.csv」というファイル名のつもりでした。フォルダ名のdirと拡張子の.csvはそのまま読めるのに、日本語の部分だけダブルクォートと数字の並びに変わっています。この記事では、この正体と、直すときに確かめた2つの設定をまとめます。
直すまでの流れ
- 1. 数字の並びに気づくgit statusなどの出力で、日本語名だけ様子が違う
- 2. core.quotepathを疑うgitが「普通でない文字」をエスケープしていないか確かめる
- 3. falseにして試す直らなければ、今度は画面側の文字コードを疑う
- 4. コンソールの文字コードも合わせる両方を一緒に設定する
数字の並びの正体: core.quotepath
gitの設定 core.quotepath の公式ドキュメントには、次のように説明されています。
Commands that output paths ... will quote "unusual" characters in
the pathname by enclosing the pathname in double-quotes and
escaping those characters with backslashes ... or bytes with
values larger than 0x80 (e.g. octal \302\265 for "micro" in
UTF-8). If this variable is set to false, bytes higher than 0x80
are not considered "unusual" any more ... The default value is
true.
つまり、既定(true)では、0x80以上のバイト値(日本語などのマルチバイト文字はここに含まれます)を「普通でない文字」として、ダブルクォートで囲み、8進数でエスケープして表示する仕様です。見えていた数字の並びは、文字が壊れたのではなく、gitがわざとエスケープして表示していたものでした。なお、ダブルクォートそのものやバックスラッシュ、制御文字は、この設定に関わらず常にエスケープされます。
core.quotepathをfalseにする
この挙動を止めるには、設定をfalseにします。
git -c core.quotepath=false status --porcelain
# または、恒久的に
git config --global core.quotepath false
これで、日本語名のファイルも8進数にエスケープされず、そのままのバイト列(UTF-8)で出力されるようになります。
それでも文字化けするなら、画面側の文字コードを疑う
私の環境では、これだけではまだ終わりませんでした。gitが出すUTF-8のバイト列を、PowerShellの画面がどの文字コードとして解釈するかが、別に関わってきます。.NETの公式ドキュメントには、コンソールの表示用の文字コードについて次のように説明されています。
The console uses the output encoding to translate characters
written by an application into corresponding console display
characters. The default code page that the console uses is
determined by the system locale.
つまり、既定の文字コードはシステムのロケール(地域と言語の設定)で決まります。日本語のWindowsでは、Microsoftのコードページ一覧によると、既定は932(Shift-JIS)です。gitが出すのはUTF-8のバイト列なので、画面側がShift-JIS(932)のつもりで読むと、文字が一致せず文字化けします。
# PowerShellの画面(コンソール)の文字コードをUTF-8に合わせる
[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false)
$falseはBOM(先頭に付く印)を付けない指定です。これで、gitが出すUTF-8のバイト列と、PowerShellが解釈する文字コードがそろいます。
片方だけでは直らない
私の環境で実際に効いたのは、core.quotepathとコンソールの文字コードの、両方を同時に設定したときでした。
| 設定 | 直すもの |
|---|---|
core.quotepath=false | gitが数字の並び(8進数エスケープ)で表示するのを止める |
[Console]::OutputEncodingをUTF-8に | PowerShellの画面が、gitの出力を正しい文字として表示する |
どちらか一方だけでは、数字の並びは消えても別の文字に化けたままだったり、設定を変えても数字の並びのまま残ったりします。両方をセットで確かめてください。
気づきにくい失敗につながることがある
私のスクリプトでは、この文字化けのせいで、後続のPowerShellの処理(Test-Path)が「パスに無効な文字が含まれています」というエラーを返していました。スクリプトの作りによっては、このエラーを拾わずに「そのファイルは無い」という扱いで静かに処理を飛ばしてしまうことがあります。コミット自体は成功して見えるため、日本語名のファイルだけ特定の処理から漏れていることに気づきにくくなります。gitの出力をスクリプトで解析する処理を書くときは、最初からこの2つの設定を入れておくほうが安全です。
まとめ
- 数字の並びは文字化けではなく、
core.quotepath(既定true)によるgitの意図的なエスケープ表示 core.quotepath=falseにすると、日本語名もエスケープされずそのまま出力される- それでも文字が合わないときは、PowerShellのコンソールの文字コード(既定はシステムロケール、日本語なら932)をUTF-8に合わせる
- 2つの設定は両方必要。片方だけでは直らない
- 自動化スクリプトでgitの出力を解析するときは、文字化けが原因で特定のファイルだけ静かに処理から漏れることがある
日本語を含むファイル名でアップロードが失敗した別の例は、紙の書類をスキャンして文字を起こし、Notionに保存する流れにも書きました。日本語を含むスクリプト自体の保存方法(BOM付きUTF-8)は、WindowsのタスクスケジューラでClaude Codeを毎日自動で動かすにまとめています。