バッチファイルで日本語名のファイルやフォルダを扱うと、「見つからない」「文字化けして別名として扱われる」「for /f で途中までしか読めない」といった問題が起きがちです。
主因はコードページとエンコーディング、そしてクォートや予約文字の扱いです。ここでは cmd.exe 前提で、安全に日本語ファイル名を操作するための要点と実用レシピをまとめます。
前提を整える:コードページと保存形式
まず現在のコンソールのコードページを chcp
で確認します。932 は Shift‑JIS、65001 は UTF‑8 を意味します。レガシーコマンドの安定性を重視するなら 932 のまま、UTF‑8 の入出力を扱うなら処理の直前だけ 65001 に切り替え、終了時に戻す方法が無難です。バッチ本体は極力 ASCII のみで記述し、日本語リテラルは変数や外部ファイル経由に逃がすと事故が減ります。
@echo off
setlocal
for /f "tokens=2 delims=: " %%A in ('chcp ^| find ":"') do set "_origCP=%%A"
chcp 65001 >nul
rem UTF-8 を扱う処理…
chcp %_origCP% >nul
endlocal
基本動作:常に二重引用符で囲み、変数も「”%VAR%”」で参照する
日本語や空白を含むパスは必ず二重引用符で囲みます。変数展開も同様に "%VAR%"
で参照します。start
は先頭引数をウィンドウタイトルと解釈するため、空タイトル ""
を先につけるのが安全です。
@echo off
set "SRC=C:\data\レポート 2025\集計.xlsx"
set "DST=C:\backup\集計.xlsx"
copy "%SRC%" "%DST%"
start "" "C:\Program Files\Excel\excel.exe" "%DST%"
for /f の罠を避ける:delims= と usebackq を明示し、UTF‑8 は PowerShell 経由
for /f
は既定で空白区切り・トリムを行うため、日本語名が切れます。行全体を受ける delims=
を必ず指定します。UTF‑8 のリストを読む必要がある場合は、cmd だけで完結させず PowerShell に委譲してエンコーディングを明示します。
@echo off
rem そのまま行全体を読む
for /f "usebackq delims=" %%F in ("files.txt") do echo "%%F"
rem UTF-8 の一覧を安全に読む
for /f "usebackq delims=" %%F in (`
powershell -NoProfile -Command "Get-Content -Encoding UTF8 -Path 'C:\list_utf8.txt'"
`) do echo "%%F"
移動・コピーの堅牢化:robocopy と PowerShell を活用する
copy
や xcopy
は名前解釈で躓きやすい場面があります。フォルダ単位の移送は robocopy
が堅牢です。ファイル単位の厳密な扱いは PowerShell 経由の Copy-Item -LiteralPath
が確実です。
@echo off
robocopy "C:\data\売上" "D:\bk\売上" /E /COPY:DAT
powershell -NoProfile -Command ^
"Copy-Item -LiteralPath 'C:\data\レポート 2025\集計.xlsx' -Destination 'D:\bk\集計.xlsx' -Force"
長い日本語パスを扱う:\?\ プレフィックスと長いパス許可
深い階層や長い日本語名で MAX_PATH を超える場合は、特殊プレフィックス \\?\
を付けると多くの API が長いパスを扱えます。OS 設定で「長いパスを有効化」しておくと成功率が上がります。
@echo off
set "P=\\?\C:\very\long\日本語\とても\長い\パス\ファイル.txt"
type "%P%"
遅延展開と感嘆符:! を壊さない読み方
遅延展開(EnableDelayedExpansion
)中は !
が変数区切りになるため、ファイル名に !
を含む場合は欠落します。該当箇所だけ一時的に DisableDelayedExpansion
に切り替えると保持できます。
@echo off
setlocal EnableDelayedExpansion
for /f "usebackq delims=" %%F in ("list_ja.txt") do (
set "X=%%F"
setlocal DisableDelayedExpansion
echo "%X%"
endlocal
)
endlocal
コンソール表示の確認:フォントと /U の使いどころ
文字が正しく存在しても、コンソールが表示できないと化けたように見えます。cmd のプロパティで TrueType の「Lucida Console」や「Consolas」を選ぶと表示が安定します。パイプ出力を Unicode UTF‑16LE にしたい場合は cmd /U
を使いますが、生成物のエンコーディングが混在すると別の不具合を招くため、流れ全体で統一することが重要です。
cmd /U /C "dir /b > C:\work\names_utf16.txt"
日本語の直接記述を減らす:変数化・外部化で安定運用
バッチ本文に非 ASCII を直接書くほど環境差の影響を受けます。日本語は変数や設定ファイルに外出し、バッチは ASCII で記述すると移植性が上がります。UTF‑8 の値を扱う必要がある場合は PowerShell で読み込んで受け渡す方針が安全です。
@echo off
for /f "usebackq delims=" %%S in (`
powershell -NoProfile -Command "$PSDefaultParameterValues['Out-File:Encoding']='utf8'; 'レポート.xlsx'"
`) do set "FNAME=%%S"
echo "%FNAME%"
うまくいかない時の切り分け:実体と存在を個別確認する
まず変数の実体を echo("%VAR%")
で確認し、次に if exist
で存在検査を行います。存在しないのではなく、展開やクォートに問題があることが多いため、展開結果を目で見て確かめるのが最短経路です。
@echo off
set "P=C:\data\売上\2025年05月.csv"
echo("%P%")
if exist "%P%" (echo FOUND) else (echo NOT FOUND)
まとめ
日本語ファイル名を cmd で確実に扱うには、常に二重引用符で囲む、for /f には delims= を明示する、UTF‑8 の入出力は PowerShell に任せる、長いパスは \\?\ を使う、遅延展開と !
の相性に注意する、という順序で対処します。表示や生成物のエンコーディングを流れ全体で統一し、展開結果を都度確認すれば、実務でも安定して日本語ファイル名を取り扱えます。