バッチファイルで「次の処理まで5秒待つ」「サービス起動後に少し間を置いてから確認する」といった遅延処理が必要になる場面は多くあります。Windowsには timeout・ping・choice・waitfor・PowerShell の Start-Sleep など複数の手法があり、用途によって使い分けが必要です。
本記事では各手法の動作の違いを比較し、カウントダウン表示・条件付き待機・リトライループなど実運用で役立つパターンまで実践コードで解説します。
- timeout・ping・choice・waitfor・PowerShell Sleep の違いと使い分け
- timeout コマンドの全オプションと注意点
- 古い環境でも使える ping による秒数指定の待機
- choice の /t /d でタイムアウト付き確認画面を作る方法
- ミリ秒単位の精密な待機が必要なときの PowerShell Start-Sleep
- カウントダウン表示付き待機ループの実装
- ファイル出現・プロセス終了を待つ条件付き待機
- リトライ処理に待機を組み込む実践パターン
遅延実行手法の比較
| 手法 | 最小単位 | キー入力で中断 | 古い環境 | 主な用途 |
|---|---|---|---|---|
| timeout /t N | 1秒 | △(/nobreak で禁止可) | Vista以降 | 標準的な秒単位の待機 |
| ping 127.0.0.1 -n N | 約1秒 | 不可(バックグラウンド) | XP以降 | 古い環境・サイレント待機 |
| choice /t N /d Y | 1秒 | △(確認キーで即実行) | Vista以降 | タイムアウト付き確認・自動選択 |
| waitfor /t N シグナル名 | 1秒 | 不可 | Vista以降 | 外部からのシグナル待機・PC間同期 |
| PowerShell Start-Sleep | 1ミリ秒 | 不可 | PS3.0以降 | 高精度待機・ミリ秒指定 |
通常の秒単位の待機なら timeout /t N /nobreak が最もシンプルです。XP など古い環境や、キー押しで中断されると困るサイレントバッチには ping が定番です。ミリ秒単位の精密な待機が必要な場合は PowerShell Start-Sleep -Milliseconds を使います。
timeout コマンドの完全解説
Windows Vista 以降で使える標準コマンドです。/nobreak を付けるとキー入力による中断を防げます。メッセージ出力を抑制したい場合は >nul にリダイレクトします。
@echo off echo 処理1を実行中... REM 5秒待機(カウントダウンメッセージを表示する) timeout /t 5 REM 5秒待機(キー入力での中断を禁止) timeout /t 5 /nobreak REM 5秒待機(メッセージを非表示にする) timeout /t 5 /nobreak >nul echo 処理2を実行中...
REM /t 秒数 : 待機する秒数を指定(1〜99999) timeout /t 10 REM /nobreak : Enterキーや任意キーでの中断を禁止する REM Ctrl+C は引き続き有効 timeout /t 10 /nobreak REM /t -1 : 無限待機(何かキーを押すまで待ち続ける) REM pause の代わりとして使える timeout /t -1 REM 標準出力を抑制して純粋に遅延だけを挿入する timeout /t 3 /nobreak >nul 2>&1
タスクスケジューラで SYSTEM アカウントや「デスクトップとの対話を許可しない」設定で実行すると、
timeout がコンソールへの書き込みに失敗してバッチが止まる場合があります。タスクスケジューラから実行するバッチでは ping または PowerShell Start-Sleep の方が安全です。ping コマンドによる待機(古い環境・サイレント実行対応)
ping 127.0.0.1 -n (秒数+1) の形でループバックアドレスに繰り返し ping を送ることで待機を実現します。timeout が使えない Windows XP 環境や、タスクスケジューラからのサイレント実行で timeout が問題になる場合に有用です。
@echo off echo 処理1を実行中... REM 5秒待機: ping は1回目が即時なので「秒数 + 1」を指定する ping 127.0.0.1 -n 6 >nul echo 処理2を実行中... REM ループバックアドレスに疎通できない場合の代替: 存在しないIPを使う REM (応答がないため1秒ずつ確実に待つ) ping 192.0.2.1 -n 6 -w 1000 >nul
@echo off setlocal set "WAIT_SEC=10" echo %WAIT_SEC%秒待機します... call :WAIT_SECONDS %WAIT_SEC% echo 待機完了 exit /b 0 :WAIT_SECONDS REM %1秒だけ待機するサブルーチン set /a "PING_N=%1 + 1" ping 127.0.0.1 -n %PING_N% >nul goto :eof
ping 127.0.0.1 -n N は1回目が即時送信のため、「N秒待つ」には -n N+1 と指定します。ループバックアドレス(127.0.0.1)は常に応答するため各間隔は約1秒です。精度が必要な場合は PowerShell Start-Sleep を使ってください。choice コマンドでタイムアウト付き確認・自動選択を実装する
choice の /t・/d オプションを使うと、指定秒数後に自動で選択肢を選ぶ「タイムアウト付き確認画面」を作れます。「10秒後に自動でYを選択する」といった対話的なバッチに向いています。
@echo off
setlocal
echo 本番環境にデプロイします。よろしいですか?
REM /t 10 : 10秒後に自動選択、/d Y : デフォルト選択は Y
choice /t 10 /d Y /m "続行しますか?(10秒で自動 Y)"
if %ERRORLEVEL% equ 1 (
echo [YES] デプロイを実行します
REM デプロイ処理...
) else (
echo [NO] キャンセルしました
exit /b 0
)
endlocal
@echo off REM 5秒待機。何かキーを押すとすぐに次へ進む echo 5秒後に処理を開始します(キー入力でスキップ可能) choice /t 5 /d Y /n /m "" >nul echo 処理を開始します
/n は選択肢の表示を非表示にします。/m "メッセージ" でプロンプト文字列をカスタマイズできます。choice の詳細な使い方はy/n確認の完全ガイドも参照してください。waitfor コマンドでシグナル待機・PC 間同期を実装する
waitfor は名前付きシグナルを待機するコマンドです。別のバッチやコンピューターから waitfor /s PC名 /si シグナル名 でシグナルを送信し、受信側が処理を再開します。/t でタイムアウト秒数も指定できます。
@echo off
setlocal
REM シグナル "batchstart" を最大30秒待機する
echo シグナルを待機中(最大30秒)...
waitfor /t 30 batchstart
set RC=%ERRORLEVEL%
if %RC% equ 0 (
echo [OK] シグナルを受信しました
) else if %RC% equ 1 (
echo [TIMEOUT] 30秒タイムアウトで処理を続行します
) else (
echo [ERROR] waitfor エラー: RC=%RC%
)
REM 後続処理...
endlocal
REM === sender.bat: シグナルを送信する側 === @echo off echo データ処理完了。受信側バッチにシグナルを送信します REM ローカルPCにシグナルを送信 waitfor /si batchstart REM 別のPCにシグナルを送信(ネットワーク同期用) REM waitfor /s SERVER01 /si batchstart echo シグナル送信完了
waitfor の主なユースケースは「サーバーAの処理が終わったらサーバーBで処理を開始する」といった複数マシン間のバッチ同期です。シグナル名は英数字で指定し、同一LAN内からのみ受信できます。タイムアウト後の処理もきちんと実装しておくのがポイントです。PowerShell Start-Sleep でミリ秒単位の高精度待機
timeout や ping は1秒単位の待機ですが、PowerShell の Start-Sleep は-Milliseconds でミリ秒単位の精密な待機が可能です。また、タスクスケジューラや SYSTEM アカウントから実行する場合でも安定して動作します。
@echo off REM 5秒待機(秒単位) powershell -NoProfile -Command "Start-Sleep -Seconds 5" REM 500ミリ秒待機(0.5秒) powershell -NoProfile -Command "Start-Sleep -Milliseconds 500" REM 2.5秒待機(小数も指定可能) powershell -NoProfile -Command "Start-Sleep -Seconds 2.5" REM 変数から秒数を渡す set "WAIT=10" powershell -NoProfile -Command "Start-Sleep -Seconds %WAIT%"
@echo off
setlocal
REM サービス起動後に少し待ってから確認する例
echo サービスを起動中...
net start MyService >nul 2>&1
REM 起動完了まで3秒待機(タスクスケジューラ対応のPowerShell版)
powershell -NoProfile -Command "Start-Sleep -Seconds 3"
REM サービス状態を確認
sc query MyService | findstr /i "RUNNING" >nul
if %ERRORLEVEL% equ 0 (
echo [OK] サービス起動確認
) else (
echo [NG] サービス未起動
exit /b 1
)
endlocal
カウントダウン表示付き待機ループを実装する
for /l ループと timeout /t 1 を組み合わせると、「あと◯秒」と残り時間を表示しながら待機する処理を実装できます。バックアップや処理待ちの進捗表示として使えます。
@echo off
setlocal enabledelayedexpansion
set "WAIT_SEC=10"
for /l %%I in (%WAIT_SEC%,-1,1) do (
REM
で行頭に戻り、同じ行を上書きする
set /p "=処理開始まであと %%I 秒... " <nul
timeout /t 1 /nobreak >nul
)
REM 最後に改行を出力して表示を整える
echo.
echo 処理を開始します
endlocal
@echo off
setlocal
echo 5秒後に処理を開始します。中断する場合は Ctrl+C を押してください。
for /l %%I in (5,-1,1) do (
echo 残り %%I 秒
timeout /t 1 /nobreak >nul
)
echo 処理を開始します...
REM 本処理...
endlocal
set /p で改行なし出力をするset /p "=テキスト" <nul は改行なしでテキストを出力するテクニックです。\r を組み合わせると同じ行を上書きできます。ただし <nul の書き方はスクリプト中では< を直接書かないよう注意してください(HTMLエスケープが必要な環境では <nul と書く)。条件付き待機の実践パターン
単純な「N秒待つ」だけでなく、「ファイルが出現するまで待つ」「プロセスが終了するまで待つ」といった条件付き待機を実装することで、より堅牢なバッチを作れます。
@echo off
setlocal
set "TARGET_FILE=C:\data\output.csv"
set "MAX_WAIT=60"
set "INTERVAL=5"
set /a "COUNT=%MAX_WAIT% / %INTERVAL%"
:WAIT_FILE
if exist "%TARGET_FILE%" (
echo [OK] ファイルを検出: %TARGET_FILE%
goto :FOUND
)
set /a "COUNT-=1"
if %COUNT% leq 0 (
echo [TIMEOUT] ファイルが見つかりませんでした: %TARGET_FILE%
exit /b 1
)
echo ファイル待機中... 残り試行%COUNT%回
timeout /t %INTERVAL% /nobreak >nul
goto :WAIT_FILE
:FOUND
REM ファイル検出後の処理...
endlocal
@echo off
setlocal
set "TARGET_PROC=notepad.exe"
set "MAX_WAIT=120"
set "ELAPSED=0"
:WAIT_PROC
tasklist /fi "IMAGENAME eq %TARGET_PROC%" 2>nul | findstr /i "%TARGET_PROC%" >nul
if %ERRORLEVEL% neq 0 (
echo [OK] プロセス終了を確認: %TARGET_PROC%
goto :PROC_DONE
)
if %ELAPSED% geq %MAX_WAIT% (
echo [TIMEOUT] プロセスがタイムアウトしました: %TARGET_PROC%
exit /b 1
)
set /a "ELAPSED+=5"
echo プロセス終了待ち... %ELAPSED%秒経過
timeout /t 5 /nobreak >nul
goto :WAIT_PROC
:PROC_DONE
echo 後続処理を開始します
endlocal
プロセス終了を待つ方法のより詳細な解説はプロセスの終了を待つ完全まとめも参照してください。ファイルの変化を継続的に監視するパターンはファイルの存在を監視するバッチ完全ガイドで詳しく解説しています。
リトライループに待機を組み込む実践パターン
ネットワークアクセスやサービス呼び出しが失敗したとき、少し待ってから再試行するリトライパターンに待機を組み込む方法です。
@echo off
setlocal
set "MAX_RETRY=5"
set "RETRY=0"
set "WAIT_SEC=5"
:RETRY_LOOP
set /a "RETRY+=1"
echo [試行%RETRY%/%MAX_RETRY%] 処理を実行中...
REM 実行するコマンド(例: ファイルコピー)
xcopy "\\server\share\data" "C:\local\data\" /y /q >nul 2>&1
set RC=%ERRORLEVEL%
if %RC% equ 0 (
echo [OK] 処理成功
goto :DONE
)
echo [NG] 失敗: ERRORLEVEL=%RC%
if %RETRY% geq %MAX_RETRY% (
echo [ERROR] %MAX_RETRY%回試行しましたが失敗しました
exit /b 1
)
REM 待機時間を倍増させる指数バックオフ(5→10→20→40→80秒)
echo %WAIT_SEC%秒後にリトライします...
timeout /t %WAIT_SEC% /nobreak >nul
set /a "WAIT_SEC*=2"
goto :RETRY_LOOP
:DONE
endlocal
@echo off
setlocal
set "SERVICE=Spooler"
set "MAX_RETRY=10"
set "RETRY=0"
REM サービス起動指示
net start "%SERVICE%" >nul 2>&1
:CHECK_SERVICE
set /a "RETRY+=1"
if %RETRY% gtr %MAX_RETRY% (
echo [ERROR] サービス起動確認タイムアウト
exit /b 1
)
sc query "%SERVICE%" | findstr /i "RUNNING" >nul 2>&1
if %ERRORLEVEL% equ 0 (
echo [OK] サービス %SERVICE% が起動しました
goto :SERVICE_READY
)
echo [待機] サービス起動中... %RETRY%/%MAX_RETRY%
timeout /t 3 /nobreak >nul
goto :CHECK_SERVICE
:SERVICE_READY
REM サービスが起動してから処理を続行
echo 後続処理を開始します
endlocal
最初は短い間隔でリトライし、失敗するたびに待機時間を倍増させる戦略です。一時的なネットワーク障害や過負荷に対して有効で、連続した即時リトライによるサーバー負荷を抑えられます。待機時間に上限(
if %WAIT_SEC% gtr 60 set "WAIT_SEC=60")を設けることも推奨します。用途別・遅延処理の使い分け早見表
| 用途 | 推奨手法 | コード例 |
|---|---|---|
| 通常の秒単位の待機 | timeout /t N /nobreak >nul | timeout /t 5 /nobreak >nul |
| タスクスケジューラ対応のサイレント待機 | ping 127.0.0.1 -n N+1 >nul | ping 127.0.0.1 -n 6 >nul |
| ミリ秒単位の高精度待機 | PowerShell Start-Sleep -Milliseconds N | powershell -Command “Start-Sleep -Milliseconds 500” |
| タイムアウト付き確認画面 | choice /t N /d Y | choice /t 10 /d Y /m “続行?” |
| ファイル出現まで待機 | if exist ループ + timeout | 上記「条件付き待機」参照 |
| プロセス終了まで待機 | tasklist ポーリング + timeout | 上記「条件付き待機」参照 |
| エラー時リトライ待機 | timeout + 指数バックオフ | 上記「リトライループ」参照 |
| PC 間バッチの同期 | waitfor シグナル名 | waitfor /t 60 batchstart |
まとめ
- timeout /t N /nobreak >nul: 最もシンプルな秒単位の待機。Vista以降の標準コマンド
- ping 127.0.0.1 -n N+1 >nul: XP対応・タスクスケジューラでも安全なサイレント待機
- choice /t N /d Y: タイムアウト付きの対話的確認。キー入力で即実行も可能
- waitfor /t N シグナル名: 外部シグナルや複数PC間の同期待機に特化
- PowerShell Start-Sleep -Milliseconds N: ミリ秒精度の待機とタスクスケジューラからの安定実行
- 条件付き待機: ファイル出現・プロセス終了を検知してから次の処理に進む堅牢なパターン
- 指数バックオフ: リトライ間隔を倍増させて一時障害に強いバッチを作る
関連記事: 処理を一時停止する方法(pause・choice) / 実行タイムアウトを設定して自動終了する方法 / プロセスの終了を待つ完全まとめ / 処理を待機させる方法(start /wait 活用)
よくある質問(FAQ)
timeout がコンソール書き込みに失敗してフリーズすることがあります。ping 127.0.0.1 -n (秒数+1) >nul かpowershell -Command "Start-Sleep -Seconds N" に変更してください。どちらも標準出力を使わないため安定して動作します。timeout は指定秒数を「最大待機時間」として扱うため、内部タイマーの都合で1秒程度短くなる場合があります。正確に5秒待機させたい場合は timeout /t 6 と1秒多めに指定するか、powershell -Command "Start-Sleep -Seconds 5" を使うと精度が上がります。ping 127.0.0.1 -n N は「N回応答を受け取るまで待つ」コマンドです。1回目は即時送受信、2回目以降は各約1秒かかるため、N回 ping は「N-1秒」の待機になります。つまり5秒待機するには -n 6、10秒なら -n 11 と指定します。waitfor は Windows Vista 以降の標準コマンドです。ただし Windows Home エディションでは一部機能が制限される場合があります。また、シグナルの送受信にはネットワーク経由の通信が必要なため、ファイアウォールや OS の設定によって受信できないことがあります。PC 内のみの同期なら waitfor /si シグナル名 で送信してください。timeout や ping は1秒単位のため、サブ秒の待機は標準コマンドでは困難です。powershell -NoProfile -Command "Start-Sleep -Milliseconds 500" を使えば500ミリ秒単位の精密な待機が実現できます。PowerShell 呼び出しのオーバーヘッド(数百ms)があるため、超高精度が必要な場合は PowerShell スクリプトとして全体を書き直す方が合理的です。

