【bat】バッチファイルで日本語ファイル名を完全攻略|文字化け・chcp・for /f・PowerShell連携・エンコーディングまで徹底解説

【bat】バッチファイルで日本語ファイル名を完全攻略|文字化け・chcp・for /f・PowerShell連携・エンコーディングまで徹底解説 bat

バッチファイルで日本語名のファイルやフォルダを扱うと、「ファイルが見つからない」「文字化けして別のファイル名として認識される」「for /f で行が途中で切れる」といった問題が頻発します。

これらの問題の根本原因は コードページとエンコーディングの不一致 にあります。cmd.exe・バッチファイル・ファイルシステム・外部コマンドがそれぞれ異なる文字コードを前提としているため、知識なく組み合わせると至る所で文字化けやエラーが発生します。

本記事では、日本語ファイル名にまつわるトラブルの原因を正確に理解し、状況に応じた確実な対処法を実際に動くコードとともに解説します。

スポンサーリンク

問題の根本原因:コードページとエンコーディング

Windows の cmd.exe は起動時に コードページ(chcp) という文字エンコーディングの設定を持ちます。日本語 Windows の既定は 932(Shift-JIS) です。

コードページ エンコーディング 対応文字 主な用途
932 Shift-JIS 日本語(ひらがな・漢字・半角カナ) 日本語 Windows の既定
65001 UTF-8 Unicode 全文字 Web・Linux 互換・多言語対応
1200 UTF-16LE Unicode 全文字 cmd /U オプション・Windows API内部
936 GB2312/GBK 中国語(簡体字) 中国語 Windows の既定

重要なのは コードページは「表示」だけでなく「コマンドへの引数の解釈」にも影響する 点です。chcp 65001 に切り替えても、コマンド自体が UTF-8 を正しく処理できるとは限りません。

バッチファイル自体のエンコーディング

見落としやすい重要ポイントです。バッチファイル(.bat / .cmd)に日本語を直接書く場合、ファイル自体を Shift-JIS(ANSI)で保存する必要があります。

ファイルのエンコーディング chcp 932(既定) chcp 65001
Shift-JIS (ANSI) ◎ 正常動作 △ 文字化けの可能性
UTF-8 (BOMなし) × 文字化け確実 ◎ 正常動作
UTF-8 (BOM付き) × BOMがコマンドとして実行されてエラー × BOM問題あり
UTF-16LE × 動作しない × 動作しない
推奨: バッチファイルは Shift-JIS で保存し、chcp 932 で動かす
メモ帳やエディタでファイルを保存するとき、エンコーディングを「ANSI」または「Shift-JIS」に指定してください。VS Code の場合はステータスバー右下のエンコーディング表示をクリックして「エンコード付きで保存」→「Shift JIS」を選びます。
日本語リテラルをバッチに直接書かず、外部ファイルや変数経由にすることでエンコーディング依存を排除できます。

chcp:コードページの確認と切り替え

現在のコードページを確認する
@echo off
chcp
rem 出力例: 現在のコード ページ: 932
UTF-8 処理時のコードページ切り替えパターン
@echo off
setlocal

rem 現在のコードページを保存
for /f "tokens=2 delims=: " %%A in ('chcp ^| findstr /r "[0-9]"') do set "_CP=%%A"

rem UTF-8 に切り替えて処理
chcp 65001 >nul

rem UTF-8 対応の処理をここに書く
powershell -NoProfile -Command "Get-Content -Encoding UTF8 -Path C:\list.txt"

rem 元のコードページに戻す
chcp %_CP% >nul
endlocal
chcp 65001 の落とし穴
UTF-8 モード(chcp 65001)に切り替えると以下のコマンドが正常動作しなくなることがあります。
set /p(ユーザー入力の読み込み)→ 入力が壊れることがある
find / findstr → 日本語検索が失敗することがある
・一部のレガシーコマンドの出力 → コードページ不一致で文字化け
UTF-8 処理は PowerShell に委譲し、バッチ自体は chcp 932 のまま動かすのが安全です。文字化けの詳しい解決法はバッチファイルの文字化けを解決する完全ガイドを参照してください。

基本原則:日本語ファイル名は必ずダブルクォートで囲む

日本語・スペース・特殊文字を含むパスは必ずダブルクォートで囲みます。変数への代入は set "VAR=値" 形式、展開時は "%VAR%" とします。

日本語パスの基本的な扱い方
@echo off
rem set "VAR=値" 形式で安全に代入
set "SRC=C:\データ\売上レポート 2025\集計.xlsx"
set "DST=C:\バックアップ\集計.xlsx"

rem 変数展開時は "%VAR%" でクォート
copy "%SRC%" "%DST%"

rem if exist でも同様
if exist "%SRC%" echo ファイルが存在します

rem start は先頭引数がウィンドウタイトルになるため "" を先付け
start "" "C:\Program Files\App\app.exe" "%DST%"

for /f で日本語ファイル名を処理する

for /f はデフォルトでスペース・タブ・セミコロンを区切り文字として扱い、行頭のセミコロンをコメント行として読み飛ばします。日本語ファイル名を安全に処理するには必ず delims= を指定します。

NG: delims= なしだと日本語が切れる
@echo off
rem 「売上 レポート.csv」のようなスペース入りファイル名が
rem 「売上」と「レポート.csv」に分割される
for /f %%F in ('dir /b "C:\データ"') do (
    echo %%F
)
OK: delims= で区切り文字を無効化
@echo off
rem delims= で区切り文字をなしにして行全体を取得
for /f "delims=" %%F in ('dir /b "C:\データ"') do (
    echo "%%F"
    copy "C:\データ\%%F" "D:\バックアップ\%%F"
)
ファイルリスト(.txt)から日本語パスを読み込む
@echo off
rem usebackq: ファイルをリストとして読む
rem delims=: 行全体を一つのトークンとして取得
rem eol=|: 行頭の | をコメントとして扱う(; を避けるため)
for /f "usebackq eol=| delims=" %%L in ("filelist.txt") do (
    if exist "%%L" (
        echo 処理中: %%L
        copy "%%L" "D:\backup\"
    )
)
eol= オプションの重要性
デフォルトの eol=; はセミコロンで始まる行をコメントとして読み飛ばします。Shift-JIS の日本語文字の2バイト目が ;(0x3B)に一致する文字(例: など)があると、その行が誤ってスキップされることがあります。eol=|eol= のようにファイル名では使わない文字を指定することで回避できます。for /f の詳しい使い方はCSVファイルを読み込む方法完全ガイドを参照してください。

dir /b で日本語ファイル名を列挙する

dir /b で日本語ファイル名を取得
@echo off
rem /b: ファイル名のみ表示
rem /a-d: ファイルのみ(フォルダを除外)
rem /s: サブフォルダも再帰検索
for /f "delims=" %%F in ('dir /b /a-d "C:\データ"') do (
    echo ファイル: %%F
)

rem フルパスで取得(/s と組み合わせ)
for /f "delims=" %%F in ('dir /b /s /a-d "C:\データ"') do (
    echo フルパス: %%F
)

UTF-8 ファイルの日本語ファイル名を処理する

ファイルリストやパス情報が UTF-8 で書かれている場合、cmd.exe の for /f では正しく読み込めません。PowerShell 経由で読み込むのが確実です。

UTF-8 ファイルリストを PowerShell 経由で読み込む
@echo off
rem PowerShell で UTF-8 ファイルを読み込み、各行をバッチに渡す
for /f "usebackq delims=" %%L in (
    `powershell -NoProfile -Command "Get-Content -Encoding UTF8 -Path 'C:\list_utf8.txt'"` 
) do (
    echo 処理中: %%L
    if exist "%%L" copy "%%L" "D:\backup\"
)
UTF-8 ディレクトリのファイル一覧を取得
@echo off
rem PowerShell でディレクトリのファイル名一覧(UTF-8)を取得
for /f "usebackq delims=" %%F in (
    `powershell -NoProfile -Command "Get-ChildItem -LiteralPath 'C:\データ' | Select-Object -ExpandProperty Name"`
) do (
    echo %%F
)

copy / robocopy / PowerShell の選択基準

コマンド 日本語ファイル名 長いパス フォルダ再帰 推奨場面
copy ◎(クォートすれば可) × × 単一ファイルのコピー
xcopy × 非推奨(robocopy に移行推奨)
robocopy フォルダ単位のコピー・移動
PowerShell Copy-Item -LiteralPath 特殊文字・長いパス・UTF-8が混在する場合
robocopy で日本語フォルダをコピー
@echo off
rem robocopy は日本語ファイル名・長いパスに標準対応
robocopy "C:\データ\売上 2025" "D:\バックアップ\売上 2025" /e /copyall

rem 特定の拡張子のみコピー
robocopy "C:\データ" "D:\バックアップ" *.xlsx *.csv /e
PowerShell でコピー・移動・削除(-LiteralPath 使用)
@echo off
rem コピー(特殊文字・日本語・長いパスに最も確実)
powershell -NoProfile -Command ^
    "Copy-Item -LiteralPath 'C:\データ\レポート.xlsx' -Destination 'D:\backup\' -Force"

rem フォルダごとコピー
powershell -NoProfile -Command ^
    "Copy-Item -LiteralPath 'C:\データ\売上' -Destination 'D:\backup\' -Recurse -Force"

rem 削除
powershell -NoProfile -Command ^
    "Remove-Item -LiteralPath 'C:\データ\古いファイル.txt' -Force"
ファイルのコピーコマンドの詳細な比較はファイルをコピーする方法完全ガイドを参照してください。

findstr で日本語文字列を検索する

findstr でファイル名や内容を日本語検索する場合は注意が必要です。

findstr での日本語検索
@echo off
rem chcp 932(Shift-JIS)の状態で実行

rem ファイル名に「売上」を含むものを検索
dir /b "C:\データ" | findstr "売上"

rem ファイルの内容から日本語文字列を検索
findstr "エラー" "C:\ログ\application.log"

rem 複数ファイルから検索
findstr /s /i "警告" "C:\ログ\*.log"

rem UTF-8 ファイルを検索する場合は PowerShell を使う
powershell -NoProfile -Command ^
    "Select-String -Path 'C:\ログ\*.log' -Pattern 'エラー' -Encoding UTF8"

ren(rename)コマンドで日本語ファイル名を変更する

ren で日本語ファイル名を変更
@echo off
rem ren "元のファイル名" "新しいファイル名"
rem ※ ren はパスを含めず、カレントフォルダ内のファイル名だけ指定
cd /d "C:\データ"
ren "売上レポート 旧.xlsx" "売上レポート 新.xlsx"

rem 別フォルダのファイルをリネームする場合
pushd "C:\データ\2025"
ren "集計.csv" "集計_confirmed.csv"
popd

rem PowerShell で確実にリネーム(特殊文字や長いパスも安全)
powershell -NoProfile -Command ^
    "Rename-Item -LiteralPath 'C:\データ\旧名前.txt' -NewName '新名前.txt'"

遅延展開(!VAR!)と日本語ファイル名の相性問題

setlocal enabledelayedexpansion が有効な状態では ! が変数区切りとして解釈されます。Shift-JIS の2バイト文字の中には2バイト目が !(0x21)に一致するものがあり、ファイル名の一部が欠落することがあります。

! を含む日本語ファイル名の安全な処理
@echo off
setlocal enabledelayedexpansion

for /f "usebackq eol=| delims=" %%F in ("filelist.txt") do (
    set "LINE=%%F"
rem 遅延展開を一時無効にして日本語文字列を安全に処理
    setlocal disabledelayedexpansion
    echo %LINE%
    copy "%LINE%" "D:\backup\"
    endlocal
)
endlocal
Shift-JIS と 0x21 の関係
Shift-JIS では一部の全角文字が2バイト構成で、2バイト目が 0x21!)になる場合があります。遅延展開有効時にこの文字が変数の区切りとして解釈されると、ファイル名の後半が切れてしまいます。日本語ファイル名を for /f で処理しながら遅延展開も使う場合は、setlocal disabledelayedexpansion で一時的に無効化してください。
遅延展開の詳細はsetlocal enabledelayedexpansion 完全ガイドを参照してください。

バッチ内に日本語リテラルを書くリスクと外部化

バッチファイル本文に日本語を直接書くと、エンコーディングの違いで動かなくなるリスクがあります。重要な文字列は外部ファイルや変数経由で管理する「外部化」が移植性を高めます。

日本語文字列を外部ファイルから読み込む
@echo off
rem config.txt に日本語設定を書いておき、バッチから読み込む
rem config.txt の内容(Shift-JIS 保存):
rem   TARGET_DIR=C:\データ\売上
rem   OUTPUT_DIR=D:\バックアップ

for /f "usebackq eol=# delims=" %%L in ("config.txt") do (
    for /f "tokens=1,2 delims==" %%A in ("%%L") do (
        set "%%A=%%B"
    )
)

echo バックアップ元: %TARGET_DIR%
echo バックアップ先: %OUTPUT_DIR%
robocopy "%TARGET_DIR%" "%OUTPUT_DIR%" /e

コンソールの日本語表示とフォント設定

正しくコードページが設定されていても、コンソールのフォントが対応していないと日本語が豆腐(□)や ? として表示されることがあります。

コンソールフォントをスクリプトから設定する(PowerShell)
rem コマンドプロンプトのプロパティで手動設定する場合:
rem  1. コマンドプロンプトのタイトルバーを右クリック
rem  2. 「プロパティ」→「フォント」タブ
rem  3. 「MS ゴシック」または「BIZ UDゴシック」を選択

rem Windows Terminal を使う場合は日本語フォントの設定が不要
rem(デフォルトで Cascadia Code / Consolas + fallback が有効)
Windows Terminal の利用を推奨
旧来の cmd.exe ウィンドウと比べ、Windows Terminal は UTF-8 を含む多言語表示が大幅に改善されています。開発環境では Windows Terminal の使用を強く推奨します。

デバッグ:日本語ファイル名トラブルの切り分け方

日本語ファイル名トラブルのデバッグ手順
@echo off
set "TARGET=C:\データ\売上レポート 2025.xlsx"

rem ステップ1: 変数の内容を確認(ブラケットで前後スペースも可視化)
echo [%TARGET%]

rem ステップ2: ファイルの存在確認
if exist "%TARGET%" (
    echo ファイルが見つかりました
) else (
    echo ファイルが見つかりません
    echo  → パス・エンコーディング・クォートを確認
)

rem ステップ3: dir で実際のファイル名を確認(Shift-JIS モードで)
dir "C:\データ" /b

rem ステップ4: @echo on でコマンドの展開状態を確認
@echo on
copy "%TARGET%" "D:\backup\"
@echo off

よくある問題パターンと解決策

症状 原因 解決策
コピーしようとするとファイルが見つからない クォートなし / 変数展開でスペース分割 "%VAR%" でクォートして展開
for /f でファイル名が途中で切れる delims= 未指定でスペース区切り for /f "delims=" を使う
for /f で特定の行が読み飛ばされる eol=; の既定設定に一致する文字 eol=| など使わない文字を指定
echo や set で日本語が文字化けする バッチファイルのエンコーディングがUTF-8 バッチを Shift-JIS で保存し直す
chcp 65001 にしたら set /p が動かない UTF-8 モードとコマンドの非互換 set /p は chcp 932 のまま使う
遅延展開有効時にファイル名が欠ける Shift-JIS の2バイト目が ! に一致 setlocal disabledelayedexpansion で一時無効化
UTF-8 のファイルリストが読めない cmd.exe の for /f は UTF-8 非対応 PowerShell Get-Content -Encoding UTF8 経由で読む
findstr で日本語が検索できない chcp と検索文字列のエンコーディング不一致 chcp 932 のまま Shift-JIS で検索、または PowerShell Select-String
日本語フォルダ名でロボコピーが失敗する コマンド構文の誤り フォルダパスをクォートで囲む

実践スクリプト:日本語ファイル名のファイルを安全にバックアップ

backup_jp.bat
@echo off
setlocal

rem 引数チェック
if "%~1"=="" (
    echo 使い方: backup_jp.bat "バックアップ元フォルダ" "保存先フォルダ"
    echo 例: backup_jp.bat "C:\データ\売上 2025" "D:\バックアップ"
    exit /b 1
)

set "SRC=%~1"
set "DST=%~2"

if not exist "%SRC%\" (
    echo エラー: バックアップ元が見つかりません
    echo  パス: %SRC%
    exit /b 1
)

rem 現在のコードページを保存して Shift-JIS を確認
for /f "tokens=2 delims=: " %%A in ('chcp ^| findstr /r "[0-9]"') do set "_CP=%%A"

rem タイムスタンプ生成
for /f "tokens=1-3 delims=/" %%a in ("%DATE%") do set "D=%%a%%b%%c"
for /f "tokens=1-2 delims=:." %%a in ("%TIME: =0%") do set "T=%%a%%b"

set "DEST=%DST%\backup_%D%_%T%"

echo バックアップ開始
echo  元: %SRC%
echo  先: %DEST%

rem robocopy で日本語ファイル名・長いパスに対応したコピー
robocopy "%SRC%" "%DEST%" /e /copyall /r:3 /w:5 /256

if %errorlevel% leq 1 (
    echo バックアップ完了
) else (
    echo エラー: バックアップ中に問題が発生しました (code=%errorlevel%)
    exit /b 1
)

endlocal

よくある質問(FAQ)

バッチファイルを UTF-8 で書きたい場合はどうすればよいか?
バッチ冒頭に chcp 65001 >nul を書き、ファイルを「UTF-8 (BOMなし)」で保存します。ただし set /p(ユーザー入力)や一部のコマンドが正常動作しなくなる場合があります。日本語ファイル名の操作には引き続き問題が出るため、日本語処理は PowerShell に委譲し、バッチ本体は Shift-JIS のままにするのが現実的です。
for /f でセミコロン(;)で始まる行が読み飛ばされる
デフォルトの eol=; の動作です。for /f "eol=| delims=" のように、ファイル名や行の先頭には出現しない文字を eol= に指定してください。eol= だけで区切り文字を消すことはできないため、delims= と組み合わせます。
dir /b で日本語ファイル名が「?」になる
コードページが合っていません。chcp で確認し、932(Shift-JIS)になっているか確認してください。Windows Terminal で実行している場合はフォント・エンコーディング設定も確認します。また、バッチファイルのエンコーディングが UTF-8 になっていると echo や set の出力が文字化けする場合があります。
PowerShell の -LiteralPath と -Path の違いは?
-Path はワイルドカード(*?)を展開します。-LiteralPath は文字をそのまま解釈するため、[] などの特殊文字を含む日本語パスでも正しく動作します。日本語ファイル名を扱う場合は常に -LiteralPath を使ってください。
robocopy と PowerShell Copy-Item のどちらを使えばよいか?
フォルダ単位の大量コピーや同期処理には robocopy が高速で使いやすいです。特殊文字・日本語・長いパスが混在する場合や、コピー成功・失敗を細かく制御したい場合は PowerShell Copy-Item -LiteralPath が確実です。
バッチで日本語の echo メッセージが文字化けする(VS Code で書いている)
VS Code のデフォルト保存エンコーディングは UTF-8 です。ステータスバー右下の「UTF-8」をクリックし、「エンコード付きで保存」→「Shift JIS」を選んでください。または設定で "files.encoding": "shiftjis" を .bat ファイルに設定します。文字化けの詳細はバッチファイルの文字化けを解決する完全ガイドを参照してください。

まとめ

バッチファイルで日本語ファイル名を安全に扱うポイントをまとめます。

  • バッチ自体を Shift-JIS(ANSI)で保存する(UTF-8 は文字化けの原因)
  • 日本語パスは必ずダブルクォートで囲む"%VAR%" 形式)
  • for /f"eol=| delims=" を必ず指定(スペース区切りと行スキップを防ぐ)
  • UTF-8 ファイルの読み込みは PowerShell 経由Get-Content -Encoding UTF8
  • フォルダコピーは robocopy、特殊文字が多い場合は PowerShell -LiteralPath
  • 遅延展開有効時は setlocal disabledelayedexpansion で一時無効化(Shift-JIS の ! 問題)
  • デバッグは echo [%VAR%]if exist で確認

バッチファイルの変数展開に関するトラブルはバッチファイルの変数展開トラブル完全解決ガイド、パスの長さ制限についてはWindowsのパス長制限(MAX_PATH=260)完全攻略も参照してください。