バッチファイルで「改行」が必要な場面は大きく2つあります。ひとつは画面出力での空行・段落分け、もうひとつはファイルに書き込む改行コード(CRLF/LF)の制御です。さらに「変数の中に改行を含める」という高度な技法も存在します。この記事ではそれぞれのケースを体系的に解説します。
echo.・echo:・echo/の違いと使い分け^(行継続文字)でコマンドを複数行に分割する方法- 変数の中に改行コードを埋め込む裏技(遅延展開との組み合わせ)
- テキストファイルへ改行を書き込む方法
- CRLF(Windows)と LF(Unix)の違いと PowerShell での変換
- 改行コードが原因で起きるトラブルと対処法
- 実践例3本(整形表示・ヘルプメッセージ・ファイル生成)
1. echo. / echo: / echo/ で空行を出力する
画面に空行(改行のみの行)を出力する最も基本的な方法は echo. です。ただし echo. 以外にも同じ目的で使われる書き方があり、それぞれ微妙な違いがあります。
| 書き方 | 動作 | 推奨度・注意点 |
|---|---|---|
echo. |
空行を出力(最も一般的) | ★★★ ただし echo. という名前のファイルがあると誤動作する |
echo: |
空行を出力 | ★★★ ファイル名の誤動作なし・高速・推奨 |
echo/ |
空行を出力 | ★★☆ 動作するが一部環境で挙動が異なる場合あり |
echo( |
空行を出力 | ★★☆ 動作するがコードの可読性が低い |
echo (末尾スペース) |
スペース1文字を出力(空行ではない) | ★☆☆ 非推奨 |
@echo off echo === 処理開始 === echo. echo ステップ1: ファイルをコピーしています... echo. echo ステップ2: データを検証しています... echo. echo === 処理完了 ===
echo. はカレントディレクトリに echo. という名前のファイルが存在すると、そのファイルを開こうとしてエラーになるという既知の問題があります。実務では echo: を使うのが最も安全です。echo. と同じ空行を出力しますが、ファイル名との衝突問題がありません。1-1. echo. を使った出力の整形例
@echo off :: ヘッダーとフッターで区切り線を入れる echo ======================================== echo バックアップ処理 echo %DATE% %TIME% echo ======================================== echo: echo 処理対象: C:\data\ echo 保存先 : D:\backup\ echo: echo 処理を開始します...
2. ^ 行継続文字:コマンドを複数行に分割する
長いコマンドは ^(キャレット)を行末に置くことで、次の行に継続して書けます。コマンドプロンプトはこれを1行として解釈します。
@echo off
:: robocopy コマンドを複数行に分割して可読性を上げる
robocopy ^^
C:\source ^^
D:\destination ^^
/mir ^^
/r:3 ^^
/w:10 ^^
/log:D:\logs\backup.log
:: xcopy も同様
xcopy "C:\My Documents\*.docx" ^^
"D:\backup\documents\" ^^
/y /i
^ の直後には改行のみが来る必要があります。^ (キャレット + スペース)にしてしまうと行継続にならず、^ がエスケープ文字として次の文字(スペース)をエスケープしてしまいます。テキストエディタの「行末スペースの自動除去」機能がある場合は安心ですが、目視で確認するのが確実です。2-1. ^ でコマンドを継続するときの注意(コメントの扱い)
@echo off
:: OK: コメントは継続行の前に置く
:: ログ付きコピー
xcopy C:\src D:\dst /y /i ^^
/exclude:C:\exclude.txt
:: NG: 継続行の途中に :: コメントを挟むとエラーになる
:: xcopy C:\src D:\dst /y /i ^ ← ここに :: を書くと壊れる
:: /exclude:C:\exclude.txt
2-2. IF・FOR 内でのコマンド複数行展開
@echo off
:: if 文内のコマンドブロックは括弧で囲めば自然に複数行にできる
if exist "C:\data\input.csv" (
echo ファイルが見つかりました
copy "C:\data\input.csv" "D:\backup\"
echo コピー完了
) else (
echo ファイルが見つかりません
exit /b 1
)
:: for ループも同様に括弧内で複数行に書ける
for %%F in (*.log) do (
echo 処理中: %%F
copy "%%F" "D:\archive\"
)
閉じ括弧
) が来るまでは自動的に継続行として扱われるため、if ( ... ) や for (...) do ( ... ) の中は^ なしで自然に複数行に分けられます。可読性が高いのでこちらを積極的に活用してください。3. 変数の中に改行コードを埋め込む
バッチファイルには「変数に改行を格納する」という少し高度な技法があります。複数行のメッセージを1つの変数にまとめて扱いたいときに便利です。
3-1. ^ と遅延展開を使う方法(クラシックな手法)
@echo off setlocal enabledelayedexpansion :: 改行コードを変数に格納する :: 重要: set ^NL=^ の後に「空行を2行」入れることで改行文字が格納される (set ^NL=^ ) :: 使い方:!NL! で改行を挿入 set MSG=1行目!NL!2行目!NL!3行目 echo !MSG!
変数に改行を埋め込む方法はトリッキーで、環境によって動作が変わります。複数行メッセージの表示には、素直に
echo を複数回呼ぶか、type でテキストファイルを表示する方法の方が確実です。3-2. より確実な方法:echo を複数回呼ぶ
@echo off :: シンプルで確実:echo を複数行に分けて書く :show_help echo 使い方: echo: echo backup.bat [オプション] echo: echo オプション: echo --src コピー元フォルダ echo --dst コピー先フォルダ echo --log ログファイルのパス echo: echo 例: echo backup.bat --src C:\data --dst D:\backup --log C:\logs\bk.log goto :eof
3-3. テキストファイルを事前に用意して type で表示する
@echo off
:: 複雑な複数行メッセージはファイルに分離する
if "%1"=="/?" (
type "%~dp0help.txt"
exit /b 0
)
:: help.txt の内容:
:: 使い方:
::
:: backup.bat [オプション]
:: ...
4. ファイルへ改行を書き込む
4-1. echo. でファイルに空行を追記する
@echo off :: テキストファイルを生成(空行あり) echo 1行目 > output.txt echo: >> output.txt echo 3行目 >> output.txt echo: >> output.txt echo 5行目 >> output.txt echo 書き込み完了 type output.txt
4-2. 複数行テキストをまとめて書き込む(ヒアドキュメント風)
@echo off
:: 括弧 + リダイレクトでまとめて書き込む(ヒアドキュメント風)
(
echo [設定ファイル]
echo:
echo TARGET_DIR=C:\data
echo BACKUP_DIR=D:\backup
echo RETAIN_DAYS=30
echo:
echo # 上記を変更する場合は管理者に連絡してください
) > config.txt
echo config.txt を生成しました
type config.txt
( echo ...; echo ... ) > ファイル の形式は、各行を個別にリダイレクトするよりもすっきりして読みやすく、パフォーマンスも向上します(ファイルを1回だけ開いて書き込む)。設定ファイル・ログヘッダーの生成に最適です。4-3. ファイルに書き込まれる改行コードについて
バッチの echo + リダイレクトで書き込まれる改行コードはCRLF(\r\n、Windows 形式)です。Unix/Linux ツールで読み込む場合は LF に変換が必要なことがあります。
| 改行コード | 表記 | 環境 | バッチでの挙動 |
|---|---|---|---|
| CRLF | \r\n / 0x0D 0x0A |
Windows | echo で書き込まれる(デフォルト) |
| LF | \n / 0x0A |
Unix / Linux / macOS | バッチ単体では直接書けない → PowerShell が必要 |
| CR | \r / 0x0D |
旧 Mac OS(現在はほぼ見ない) | バッチでは通常扱わない |
ファイルへの書き込みとリダイレクトの詳細は リダイレクト(> >> 2>&1)完全ガイド、テキストファイルの作成方法全般は テキストファイルを作成する方法 を参照してください。
5. CRLF と LF の変換(PowerShell 活用)
5-1. CRLF → LF に変換する(Linux 向けファイル生成)
@echo off
:: PowerShell で CRLF → LF に変換(BOMなし UTF-8 で保存)
powershell -Command ^^
"$text = Get-Content -Path 'input.txt' -Raw;" ^^
"$text = $text -replace '`r`n', '`n';" ^^
"[System.IO.File]::WriteAllText('output_lf.txt', $text, [System.Text.UTF8Encoding]::new($false))"
echo LF 変換完了: output_lf.txt
5-2. LF → CRLF に変換する(Windows 向けに変換)
@echo off
:: PowerShell で LF → CRLF に変換
powershell -Command ^^
"$text = [System.IO.File]::ReadAllText('input_lf.txt');" ^^
"$text = $text -replace '(?<!`r)`n', '`r`n';" ^^
"[System.IO.File]::WriteAllText('output_crlf.txt', $text)"
echo CRLF 変換完了: output_crlf.txt
5-3. PowerShell で LF のみのファイルを直接生成する
@echo off
:: LF のみで改行するファイルを PowerShell で生成
powershell -Command ^^
"$lines = @('1行目', '', '3行目', '', '5行目');" ^^
"$content = $lines -join "`n";" ^^
"[System.IO.File]::WriteAllText('lf_only.txt', $content, [System.Text.UTF8Encoding]::new($false))"
echo LF ファイル生成完了: lf_only.txt
文字コードと改行コードの問題(UTF-8・Shift-JIS・BOM)については 文字化けを直す方法完全ガイド も参照してください。
6. 改行が原因で起きるトラブルと対処法
| 症状 | 原因 | 対処法 |
|---|---|---|
echo. がファイルを開こうとするエラーが出る |
カレントに echo. という名前のファイルが存在する |
echo: に変更する |
| ファイル末尾に余分な空白行が入る | echo. の後ろにスペースが入っている |
echo: を使う、またはスペースを除去する |
| for /f がファイルの空行を読み飛ばす | for /f は仕様として空行をスキップする |
type で別の方法で処理するか PowerShell を使う |
| 変数の末尾に改行が入って比較が失敗する | set /p や for /f で取得した値に見えない CRLF が付く |
set "VAR=%VAR:"=%" でクォートを除去するか PowerShell で処理 |
| Linux サーバーに送ったファイルで改行コードが二重になる | CRLF のファイルを LF 環境で処理すると \r が残る |
送信前に CRLF → LF 変換してから転送する |
| echo で % が消える / 変数が展開されてしまう | echo は %VAR% を自動展開する |
echo %%VAR%%(バッチ内)または echo %VAR% の前に set VAR で確認 |
6-1. for /f の空行スキップ問題の回避
@echo off
:: for /f は空行をスキップするため行番号がずれる
:: 回避策1: eol に存在しない文字を指定して空行を保持
for /f "usebackq eol=| delims=" %%L in ("data.txt") do (
echo %%L
)
:: 回避策2: PowerShell で読み込む(空行も処理)
powershell -Command "Get-Content 'data.txt' | ForEach-Object { Write-Host $_ }"
変数展開のトラブル全般は 変数展開が思った通りに動かない原因と修正方法 も参照してください。
7. 実践例3本
実践例1:整形された処理結果レポートを表示する
@echo off
setlocal
:: 処理結果を整形して表示する
set SRC=C:\data
set DST=D:\backup
set FILE_COUNT=0
set ERR_COUNT=0
for %%F in ("%SRC%\*.csv") do (
set /a FILE_COUNT+=1
copy "%%F" "%DST%\" >nul 2>&1
if errorlevel 1 set /a ERR_COUNT+=1
)
:: 区切り線で整形(echo: で空行を挿入)
echo:
echo ======================================
echo 処理完了レポート
echo %DATE% %TIME%
echo ======================================
echo:
echo コピー元 : %SRC%
echo コピー先 : %DST%
echo:
echo 処理ファイル数 : %FILE_COUNT%
echo エラー数 : %ERR_COUNT%
echo:
if %ERR_COUNT% gtr 0 (
echo [警告] %ERR_COUNT% 件のコピーに失敗しました。
) else (
echo [OK] すべてのファイルを正常にコピーしました。
)
echo ======================================
echo:
実践例2:バッチファイルに /? オプションでヘルプを表示する
@echo off :: /? または --help でヘルプを表示 if /i "%~1"=="/?" goto :show_help if /i "%~1"=="--help" goto :show_help :: 通常処理 echo 処理を実行します... goto :eof :show_help echo: echo 【使い方】 deploy.bat [オプション] echo: echo 【オプション】 echo /src ^<パス^> コピー元フォルダを指定 echo /dst ^<パス^> コピー先フォルダを指定 echo /log ^<パス^> ログファイルのパスを指定 echo /dry ドライランモード(コピーしない) echo /? このヘルプを表示 echo: echo 【例】 echo deploy.bat /src C:\build /dst \\server\deploy /log C:\logs\dp.log echo: exit /b 0
echo ^<パス^> のように、< と > は^< と ^> にエスケープしないとリダイレクト文字として解釈されます。|(パイプ)も同様に ^| にしてください。実践例3:複数行の設定ファイルをバッチから生成する
@echo off
setlocal
:: 引数から設定値を受け取る
set SERVER=%~1
set PORT=%~2
set DB_NAME=%~3
:: デフォルト値
if "%SERVER%"=="" set SERVER=localhost
if "%PORT%"=="" set PORT=5432
if "%DB_NAME%"=="" set DB_NAME=myapp
:: 設定ファイルを生成(括弧 + リダイレクトで一括書き込み)
(
echo # アプリケーション設定ファイル
echo # 生成日時: %DATE% %TIME%
echo:
echo [database]
echo host = %SERVER%
echo port = %PORT%
echo dbname = %DB_NAME%
echo:
echo [logging]
echo level = INFO
echo file = C:\logs\app.log
echo:
echo # このファイルは自動生成されました
echo # 手動で変更した場合、次回実行時に上書きされます
) > app.config
echo 設定ファイルを生成しました: app.config
echo:
type app.config
@echo off の仕組みや echo コマンドの活用については @echo off を使いこなす完全ガイド も参照してください。
8. まとめ:改行パターン別チートシート
| 用途 | 方法 | ポイント |
|---|---|---|
| 画面に空行を出力 | echo: |
echo. より安全(ファイル名衝突なし) |
| コマンドを複数行に分割 | ^(行末に置く) |
^ の後にスペース・コメントを書かない |
| if/for ブロックを複数行に | 括弧 ( ... ) |
^ 不要・自然に複数行 |
| 複数行テキストをファイルに一括書き込み | ( echo ...; echo ... ) > file |
可読性・パフォーマンス◎ |
| ファイル末尾に空行を追記 | echo: >> file |
ログの区切りに便利 |
| for /f で空行を保持 | eol=| を指定 |
| は通常のテキストに出てこない文字 |
| CRLF → LF 変換 | PowerShell -replace |
Linux向けファイル生成に |
| LF のみのファイル生成 | PowerShell [IO.File]::WriteAllText |
バッチ単体では不可 |
FAQ
Qecho. と echo: どちらを使えばよいですか?
A実務では echo: を推奨します。echo. はカレントディレクトリに同名のファイルが存在するとエラーになる既知の問題があります。echo: は完全に同じ空行を出力しますが、その問題がありません。どちらも正常に動作する場合はどちらでも構いませんが、チームの規約で統一するとよいでしょう。
Q^(行継続)を使ったのにエラーになります。
Aよくある原因は ^ の後ろにスペースや他の文字が入っていることです。^ の直後は改行のみにしてください。また、rem や :: コメントの行に ^ を書くとその行も継続対象になり、意図しない動作になることがあります。
Qecho コマンドで < や > を表示するにはどうすればよいですか?
A^< と ^> にエスケープしてください。echo A ^< B は A < B と表示されます。パイプ | は ^|、アンパサンド & は ^& です。
Qバッチで生成したファイルを Linux で使うと改行コードが二重になります。
Aバッチの echo は CRLF(\r\n)で書き込みます。Linux で読み込むと \r(CR)が残って文字化けします。転送前に PowerShell で CRLF → LF 変換してください:powershell -Command "$t=Get-Content file.txt -Raw; $t=$t -replace '\`r\`n','\`n'; [IO.File]::WriteAllText('file_lf.txt',$t,[Text.UTF8Encoding]::new($false))"
Qfor /f で読み込んだ変数の末尾に謎の空白や改行が入っています。
Afor /f は行末の空白を自動的に除去しますが、ファイルの改行コードが CRLF の場合に \r が残ることがあります。set "VAR=%VAR%"(ダブルクォートで囲む)で末尾スペースを除去するか、PowerShell の Get-Content で読み込んでください。詳しくは「変数の末尾に余計な空白が入るときの対策」も参照してください。
Qヘルプテキストなど長い複数行メッセージをバッチで表示する最善の方法は?
A3つのアプローチがあります。①echo を複数行に並べる(シンプル・推奨)、②別のテキストファイルに書いておいて type help.txt で表示する(大量テキストに最適)、③PowerShell の here-string を呼び出す。長いヘルプメッセージは②のファイル分離が最も保守しやすいです。