【bat】リダイレクト(> >> 2>&1)の使い方完全ガイド|標準出力・エラー出力の制御

【bat】標準出力と標準エラーをリダイレクトする方法|> と 2> の違い bat

バッチファイルで >>> を使ってログを出力したり、2>&1 でエラーメッセージをファイルに保存したりする場面は日常的にあります。しかし「2>&1 って何?」「エラーだけを別ファイルに書き出したい」「コンソールとファイルに同時に出力したい」といった疑問を持つ方も多いのではないでしょうか。

この記事では、バッチファイルのリダイレクト記号の意味と使い方を基本から応用まで体系的に解説します。コピーしてすぐ使える実務テンプレートも豊富に用意しています。

この記事で学べること

  • 標準出力(stdout)・標準エラー出力(stderr)の違いとストリーム番号(1・2)
  • >(上書き)・>>(追記)・2>2>&1 の意味と使い方
  • エラーのみをファイルに保存・エラーを捨てる(nul)パターン
  • コンソール表示と同時にファイルへ書き出す(tee 代替)方法
  • 実務で使えるログ出力・エラーハンドリングのテンプレート集
スポンサーリンク

標準出力と標準エラー出力の違い

コマンドの出力には2種類あります。リダイレクトを使いこなすには、まずこの違いを理解することが重要です。

種類 ストリーム番号 内容 出力例
標準出力(stdout) 1 正常な実行結果 dir の一覧、echo の内容
標準エラー出力(stderr) 2 エラーメッセージ ファイルが見つかりません、アクセス拒否

ポイント:> は標準出力(1)だけをリダイレクトします。エラーメッセージ(2)は別ストリームのため、> だけではファイルに書き出されずコンソールに表示されたままになります。エラーも含めてファイルに保存したい場合は 2>&1 が必要です。

リダイレクト記号の一覧と意味

記号 意味
> 標準出力を上書きでファイルへ echo hello > out.txt
>> 標準出力を追記でファイルへ echo hello >> log.txt
2> 標準エラー出力を上書きでファイルへ cmd 2> err.txt
2>> 標準エラー出力を追記でファイルへ cmd 2>> err.txt
2>&1 標準エラーを標準出力と同じ出力先 cmd > out.txt 2>&1
>nul 標準出力を捨てる(非表示) ping 127.0.0.1 >nul
2>nul 標準エラーを捨てる(エラー非表示) del file.txt 2>nul

各リダイレクト記号の使い方

>(上書き)と >>(追記)

redirect_basic.bat
@echo off
chcp 932 >nul

:: > は上書き(ファイルが存在すれば内容を消してから書く)
echo 1回目の実行 > log.txt
echo 2回目の実行 > log.txt   ← 1回目の内容が消える

:: >> は追記(ファイルがなければ新規作成、あれば末尾に追加)
echo 1行目 > log.txt
echo 2行目 >> log.txt
echo 3行目 >> log.txt
:: → log.txt に 3行が書き込まれる

2> エラー出力のみをファイルに保存

stderr_only.bat
@echo off
chcp 932 >nul

:: 正常出力はコンソールに表示、エラーのみファイルへ
dir C:work 2> error.txt

:: エラーを追記で蓄積
xcopy C:src D:dst /E 2>> error.log

:: error.log にエラーがあれば通知
FOR %%s IN (error.log) DO IF %%~zs GTR 0 echo エラーが発生しました
pause

2>&1 標準出力とエラーを同じファイルへ

2>&1 は「ストリーム2(stderr)を、ストリーム1(stdout)が向いている先に送る」という意味です。書き順が重要で、必ず > ファイル名 2>&1 の順に書きます。

stdout_stderr.bat
@echo off
chcp 932 >nul

:: ✅ 正常出力もエラーも両方 all.log へ
xcopy C:src D:dst /E > all.log 2>&1

:: ❌ 順番を逆にすると意図通りにならない
xcopy C:src D:dst /E 2>&1 > all.log   ← NG(エラーがコンソールに出る)

:: >> で追記しながら両方まとめる
echo [%DATE% %TIME%] 開始 >> run.log 2>&1
some_command >> run.log 2>&1
echo [%DATE% %TIME%] 完了 >> run.log 2>&1
pause

注意:2>&1 > ファイル のように 2>&1 を先に書くと、エラーが「リダイレクト前のコンソール」に向いたままになり、ファイルに書き出されません。必ず > ファイル 2>&1 の順で書いてください。

>nul / 2>nul 出力を捨てる

コンソールへの余分な出力を非表示にしたいとき、nul(Windowsの「何もない場所」)にリダイレクトします。

suppress_output.bat
@echo off
chcp 932 >nul     :: chcp のコードページ変更メッセージを非表示

:: 正常出力を捨てる(処理結果をコンソールに出したくない)
ping -n 1 127.0.0.1 >nul

:: エラーを捨てる(エラーメッセージを非表示にする)
del temp.tmp 2>nul
mkdir output 2>nul        :: 既に存在してもエラーを出さない

:: 標準出力もエラーも両方捨てる
some_command >nul 2>&1

コンソール表示とファイル出力を同時に行う

バッチファイルには Linux の tee コマンドがないため、コンソールにも表示しながらファイルにも書くには工夫が必要です。

方法1:PowerShell の Tee-Object を使う

tee_output.bat
@echo off
chcp 932 >nul

:: PowerShell の Tee-Object でコンソールとファイルに同時出力
dir C:work | powershell -Command "$input | Tee-Object -FilePath log.txt"

:: 追記モード(-Append)
dir C:work | powershell -Command "$input | Tee-Object -Append -FilePath log.txt"
pause

方法2:ログ出力サブルーチンを作る(バッチのみで完結)

log_subroutine.bat
@echo off
chcp 932 >nul
setlocal
set LOGFILE=run.log

:: ログ出力サブルーチン呼び出し
call :log "処理を開始します"
call :log "ファイルをコピー中..."
copy src.txt dst.txt >nul
call :log "完了しました"
goto :eof

:: :log サブルーチン(コンソール表示 + ファイル追記)
:log
echo [%DATE% %TIME%] %~1
echo [%DATE% %TIME%] %~1 >> %LOGFILE%
exit /B

実務テンプレート集

テンプレート1:標準ログ出力(タイムスタンプ付き・エラー含む)

template_logging.bat
@echo off
chcp 932 >nul
setlocal

set TS=%DATE:~0,4%%DATE:~5,2%%DATE:~8,2%
set LOGFILE=%~dp0logsapp_%TS%.log

IF NOT EXIST "%~dp0logs" mkdir "%~dp0logs"

:: 処理開始ログ
echo ===== 開始: %DATE% %TIME% ===== >> "%LOGFILE%" 2>&1

:: メイン処理(標準出力・エラーをまとめてログへ)
xcopy "C:src" "D:dst" /E /Y >> "%LOGFILE%" 2>&1

:: 終了コードを記録
echo 終了コード: %ERRORLEVEL% >> "%LOGFILE%"
echo ===== 完了: %DATE% %TIME% ===== >> "%LOGFILE%" 2>&1

echo 完了。ログ: %LOGFILE%
pause

テンプレート2:エラーのみ別ファイルに分けて保存

template_split_log.bat
@echo off
chcp 932 >nul

set TS=%DATE:~0,4%%DATE:~5,2%%DATE:~8,2%
set OUT_LOG=logsout_%TS%.log
set ERR_LOG=logserr_%TS%.log

IF NOT EXIST logs mkdir logs

:: 正常出力とエラー出力を別々のファイルに保存
some_command > "%OUT_LOG%" 2> "%ERR_LOG%"

:: エラーログにデータがあれば報告
FOR %%f IN ("%ERR_LOG%") DO (
    IF %%~zf GTR 0 (
        echo ⚠ エラーが発生しました: %ERR_LOG%
    )
)
pause

テンプレート3:完全サイレントモード(出力を全て抑制)

template_silent.bat
@echo off
chcp 932 >nul

:: タスクスケジューラ実行時など、一切出力したくない場合
some_command >nul 2>&1

:: エラーコードだけ確認して分岐
IF %ERRORLEVEL% NEQ 0 (
    echo 処理失敗 >> error_record.log
    exit /B 1
)
exit /B 0

よくある失敗例と対処法

症状 原因 対処法
エラーメッセージがファイルに書き出されない > のみで 2>&1 を付けていない > file.log 2>&1 に変更
2>&1 を書いてもエラーがコンソールに出る 2>&1 > file と順番が逆 > file 2>&1 の順に直す
>> でログが文字化けする chcp の設定とファイルの文字コードが不一致 バッチ冒頭で chcp 932 >nul を明示する
ログファイルが毎回空になる >> のつもりで > を使っている 追記は >>(不等号2つ)を使う
del 2>nul でも「ファイルが見つかりません」が表示される スペースの位置が間違っている(del file 2>nul ではなく del file2 >nul になっている) del file.txt 2>nul(2とファイル名の間にスペース不要)を確認

まとめ

やりたいこと 書き方
正常出力をファイルに上書き command > file.log
正常出力をファイルに追記 command >> file.log
エラーのみファイルに保存 command 2> error.log
正常・エラー両方ファイルに保存 command > file.log 2>&1
正常出力を捨てる command >nul
エラーを捨てる command 2>nul
全出力を捨てる command >nul 2>&1

ポイント:最初に覚えるべき3パターンは >> log.txt(追記)・2>nul(エラー非表示)・> log.txt 2>&1(全部ログ)です。2>&1必ず > ファイル の後に書くことを忘れずに。

よくある質問

❓ リダイレクトでファイルを空にする(0バイトにする)にはどうすればいいですか? (クリックで開閉)

type nul > file.txt でファイルを0バイトに初期化できます。ファイルが存在しない場合は新規作成、存在する場合は内容を削除します。

type nul > log.txt    :: log.txt を 0 バイトに初期化
❓ ログファイルに BOM(バイトオーダーマーク)が付いてしまいます (クリックで開閉)

chcp 65001(UTF-8)環境で > リダイレクトすると、環境によっては先頭にBOMが付くことがあります。BOMなしUTF-8でログを書きたい場合は PowerShell を経由する方法が確実です。

:: PowerShell でBOMなしUTF-8で書き出す
echo 出力内容 | powershell -Command "$input | Out-File -Encoding UTF8NoBOM log.txt"
❓ FOR ループ内でリダイレクトすると毎回上書きされてしまいます (クリックで開閉)

ループ内では >(上書き)ではなく >>(追記)を使いましょう。また、ループの前にファイルを初期化してからループで追記するパターンが定番です。

:: ループ前に初期化
type nul > result.log

FOR %%f IN (*.txt) DO (
    echo %%f >> result.log    :: >> で追記
)