【bat】処理を遅延実行する完全ガイド|timeout・ping・choice・waitfor・PowerShell Sleep・カウントダウン・条件付き待機まで

【bat】処理を遅延実行する方法(timeout / ping の活用) bat

バッチファイルで「次の処理まで5秒待つ」「サービス起動後に少し間を置いてから確認する」といった遅延処理が必要になる場面は多くあります。Windowsには timeoutpingchoicewaitfor・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 にリダイレクトします。

基本的な timeout の使い方
@echo off

echo 処理1を実行中...

REM 5秒待機(カウントダウンメッセージを表示する)
timeout /t 5

REM 5秒待機(キー入力での中断を禁止)
timeout /t 5 /nobreak

REM 5秒待機(メッセージを非表示にする)
timeout /t 5 /nobreak >nul

echo 処理2を実行中...
timeout の主なオプション一覧と使い分け
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
タスクスケジューラから実行すると timeout が停止することがある
タスクスケジューラで SYSTEM アカウントや「デスクトップとの対話を許可しない」設定で実行すると、timeout がコンソールへの書き込みに失敗してバッチが止まる場合があります。タスクスケジューラから実行するバッチでは ping または PowerShell Start-Sleep の方が安全です。

ping コマンドによる待機(古い環境・サイレント実行対応)

ping 127.0.0.1 -n (秒数+1) の形でループバックアドレスに繰り返し ping を送ることで待機を実現します。timeout が使えない Windows XP 環境や、タスクスケジューラからのサイレント実行で timeout が問題になる場合に有用です。

ping による秒数待機の基本(N秒待機は -n N+1)
@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 待機の注意点
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を選択する」といった対話的なバッチに向いています。

choice でタイムアウト付き Y/N 確認を実装する
@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
choice を純粋な待機として使う(キー入力で即スキップも可能)
@echo off

REM 5秒待機。何かキーを押すとすぐに次へ進む
echo 5秒後に処理を開始します(キー入力でスキップ可能)
choice /t 5 /d Y /n /m "" >nul

echo 処理を開始します
choice の /n と /m の使い分け
/n は選択肢の表示を非表示にします。/m "メッセージ" でプロンプト文字列をカスタマイズできます。choice の詳細な使い方はy/n確認の完全ガイドも参照してください。

waitfor コマンドでシグナル待機・PC 間同期を実装する

waitfor は名前付きシグナルを待機するコマンドです。別のバッチやコンピューターから waitfor /s PC名 /si シグナル名 でシグナルを送信し、受信側が処理を再開します。/t でタイムアウト秒数も指定できます。

waitfor でタイムアウト付きシグナル待機を実装する
@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 の実用的な使い方
waitfor の主なユースケースは「サーバーAの処理が終わったらサーバーBで処理を開始する」といった複数マシン間のバッチ同期です。シグナル名は英数字で指定し、同一LAN内からのみ受信できます。タイムアウト後の処理もきちんと実装しておくのがポイントです。

PowerShell Start-Sleep でミリ秒単位の高精度待機

timeoutping は1秒単位の待機ですが、PowerShell の Start-Sleep-Milliseconds でミリ秒単位の精密な待機が可能です。また、タスクスケジューラや SYSTEM アカウントから実行する場合でも安定して動作します。

PowerShell Start-Sleep: 秒・ミリ秒単位の待機
@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 を組み合わせると、「あと◯秒」と残り時間を表示しながら待機する処理を実装できます。バックアップや処理待ちの進捗表示として使えます。

シンプルなカウントダウン表示(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
カウントダウン付き中断確認(5秒以内にEscで中断)
@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エスケープが必要な環境では &lt;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
プロセスが終了するまで待機する(tasklist ポーリング)
@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)

Qタスクスケジューラからバッチを実行すると timeout でバッチが止まってしまいます。
Aタスクスケジューラで「デスクトップとの対話を許可しない」設定や SYSTEM アカウントで実行すると、timeout がコンソール書き込みに失敗してフリーズすることがあります。ping 127.0.0.1 -n (秒数+1) >nulpowershell -Command "Start-Sleep -Seconds N" に変更してください。どちらも標準出力を使わないため安定して動作します。
Qtimeout /t 5 としたのに実際には4秒しか待機しません。
Atimeout は指定秒数を「最大待機時間」として扱うため、内部タイマーの都合で1秒程度短くなる場合があります。正確に5秒待機させたい場合は timeout /t 6 と1秒多めに指定するか、powershell -Command "Start-Sleep -Seconds 5" を使うと精度が上がります。
Qping -n 6 で5秒待機するはずが6秒かかります。
Aping 127.0.0.1 -n N は「N回応答を受け取るまで待つ」コマンドです。1回目は即時送受信、2回目以降は各約1秒かかるため、N回 ping は「N-1秒」の待機になります。つまり5秒待機するには -n 6、10秒なら -n 11 と指定します。
Qwaitfor コマンドが見当たりません。使えない環境ですか?
Awaitfor は Windows Vista 以降の標準コマンドです。ただし Windows Home エディションでは一部機能が制限される場合があります。また、シグナルの送受信にはネットワーク経由の通信が必要なため、ファイアウォールや OS の設定によって受信できないことがあります。PC 内のみの同期なら waitfor /si シグナル名 で送信してください。
Q0.5秒(500ミリ秒)など1秒未満の待機をバッチファイルで実現できますか?
Atimeoutping は1秒単位のため、サブ秒の待機は標準コマンドでは困難です。powershell -NoProfile -Command "Start-Sleep -Milliseconds 500" を使えば500ミリ秒単位の精密な待機が実現できます。PowerShell 呼び出しのオーバーヘッド(数百ms)があるため、超高精度が必要な場合は PowerShell スクリプトとして全体を書き直す方が合理的です。