【bat】バッチファイルで処理を待機させる方法(timeout・ping・choice・START /WAIT)

バッチファイルで「処理を一定時間待機させたい」「別のプログラムの完了を待ちたい」と思ったことはありませんか?

バッチファイルには timeout コマンドをはじめ、複数の待機方法が用意されています。しかし用途によって最適な方法が異なるため、正しく使い分けることが重要です。

この記事では、timeout の基本操作から ping による待機choice コマンドSTART /WAIT でのプロセス終了待ちファイル存在待ちループPowerShell 連携まで、実務で使えるあらゆる待機テクニックを網羅的に解説します。

スポンサーリンク

timeout コマンドの基本

timeout は Windows Vista 以降で使える標準の待機コマンドです。指定した秒数だけ処理を一時停止します。

基本構文

構文
timeout /t 秒数 [/nobreak]
オプション 説明
/t 秒数 待機する秒数(-1 で無限待機)
/nobreak キー入力による中断を無効化(Ctrl+C のみ有効)

基本的な使い方

timeout-basic.bat
@echo off
echo 処理を開始します...

:: 10秒間待機(キー入力で中断可能)
timeout /t 10

echo 10秒経過しました。次の処理に進みます。

実行結果

処理を開始します...

10 秒待っています。続行するには何かキーを押してください ...
10秒経過しました。次の処理に進みます。

/nobreak オプション

/nobreak を付けると、ユーザーのキー入力で待機を中断できなくなります。自動実行バッチでは必須のオプションです。

timeout-nobreak.bat
@echo off
:: キー入力では中断できない(Ctrl+C のみ有効)
timeout /t 30 /nobreak

echo 30秒の待機が完了しました。

注意:/nobreak を付けても Ctrl+C で強制中断は可能です。完全に中断を防ぐことはできません。

待機メッセージを非表示にする

timeout のカウントダウン表示が不要な場合は、出力を nul にリダイレクトします。

timeout-silent.bat
@echo off
echo 5秒間お待ちください...

:: カウントダウン表示を抑制
timeout /t 5 /nobreak > nul

echo 完了しました。

無限待機(キー入力待ち)

/t -1 を指定すると、キーが押されるまで無限に待機します。

timeout-infinite.bat
@echo off
echo 何かキーを押すと続行します...
timeout /t -1 > nul
echo 続行します。

ポイント:timeout /t -1pause コマンドと同様の動作ですが、出力メッセージのカスタマイズが可能な点が異なります。

ping コマンドによる待機(レガシー手法)

timeout コマンドが使えない古い環境(Windows XP 以前)では、ping コマンドを使った待機が定番でした。現在でもレガシーなバッチファイルで見かけることがあります。

基本的な使い方

ping-wait.bat
@echo off
echo 10秒間待機します...

:: N秒待機するには N+1 回 ping を送る
ping 127.0.0.1 -n 11 > nul

echo 待機完了。

ping で待機する仕組み

  • ping 127.0.0.1(ローカルホスト)に ping を送信
  • ping は 1回送信するごとに約1秒の間隔を空ける
  • -n 11 で11回送信 → 間隔は10回 → 約10秒の待機
  • 出力を > nul で非表示にする

注意:ping による待機は正確なタイミング保証がありません。ネットワーク設定やシステム負荷によって誤差が生じることがあります。新規開発では timeout を使用してください。

choice コマンドでの待機(タイムアウト付き選択)

choice コマンドは本来ユーザーに選択肢を提示するコマンドですが、/t(タイムアウト)と /d(デフォルト選択)を組み合わせると待機コマンドとして使えます。

基本構文

構文
choice /c YN /t 秒数 /d Y /n /m "メッセージ"
オプション 説明
/c YN 選択肢(Y と N)
/t 秒数 タイムアウトまでの秒数
/d Y タイムアウト時のデフォルト選択
/n 選択肢リスト [Y,N] の表示を抑制
/m "文字列" プロンプトメッセージ

待機コマンドとして使う例

choice-wait.bat
@echo off
echo 5秒後に自動で続行します(Y で即時続行、N で中止)

choice /c YN /t 5 /d Y /m "続行しますか?"

if %ERRORLEVEL%==2 (
  echo 中止しました。
  exit /b 1
)
echo 処理を続行します。

ポイント:choiceERRORLEVEL で選択結果を取得できます。1番目の選択肢が ERRORLEVEL=1、2番目が ERRORLEVEL=2 です。タイムアウト時はデフォルト選択肢の値が返ります。

START /WAIT でプロセス終了を待つ

外部プログラムを起動して終了するまで待機するには、START /WAIT を使います。

基本的な使い方

start-wait.bat
@echo off
echo メモ帳を起動します...

:: メモ帳が閉じられるまで待機
start /wait notepad.exe "C:\temp\test.txt"

echo メモ帳が閉じられました。次の処理に進みます。

終了コードの取得

START /WAIT で起動したプログラムの終了コードは %ERRORLEVEL% で取得できます。

start-wait-errorlevel.bat
@echo off
echo セットアップを実行します...

start /wait setup.exe /silent

if %ERRORLEVEL%==0 (
  echo インストール成功
) else (
  echo インストール失敗(コード: %ERRORLEVEL%exit /b 1
)

複数プログラムの順次実行

sequential-exec.bat
@echo off
echo === Step 1: データベースバックアップ ===
start /wait backup.exe --db
if %ERRORLEVEL% neq 0 goto :error

echo === Step 2: マイグレーション実行 ===
start /wait migrate.exe --apply
if %ERRORLEVEL% neq 0 goto :error

echo === Step 3: アプリケーション再起動 ===
start /wait restart-app.exe
if %ERRORLEVEL% neq 0 goto :error

echo すべての処理が正常に完了しました。
exit /b 0

:error
echo エラーが発生しました(コード: %ERRORLEVEL%exit /b 1

ファイル存在待ちループ

特定のファイルが作成されるのを待つパターンです。他のプロセスがファイルを出力するのを待機する場合に使います。

基本パターン

wait-for-file.bat
@echo off
set TARGET=C:\output\result.csv

echo %TARGET% の作成を待っています...

:waitloop
if exist "%TARGET%" (
  echo ファイルを検出しました。
  goto :found
)
:: 5秒待ってから再チェック
timeout /t 5 /nobreak > nul
goto :waitloop

:found
echo ファイル処理を開始します。
type "%TARGET%"

タイムアウト付きファイル待ち

無限ループを防ぐため、タイムアウトを設定するのが実務では必須です。

wait-for-file-timeout.bat
@echo off
setlocal enabledelayedexpansion

set TARGET=C:\output\result.csv
set INTERVAL=5
set MAX_WAIT=300
set ELAPSED=0

echo %TARGET% を待機中(最大 %MAX_WAIT% 秒)...

:waitloop
if exist "%TARGET%" (
  echo ファイルを検出しました(%ELAPSED% 秒後)。
  goto :found
)

if !ELAPSED! geq %MAX_WAIT% (
  echo タイムアウト: %MAX_WAIT% 秒以内にファイルが見つかりませんでした。
  exit /b 1
)

timeout /t %INTERVAL% /nobreak > nul
set /a ELAPSED+=%INTERVAL%
goto :waitloop

:found
echo 処理を続行します。

条件付き待機(IF + GOTO ループ)

ファイルの存在だけでなく、任意の条件が満たされるまで待機するパターンです。

プロセスの終了を待つ

tasklist コマンドで特定のプロセスが実行中かどうかを確認し、終了するまで待機します。

wait-for-process.bat
@echo off
set PROCESS=backup.exe

echo %PROCESS% の終了を待機中...

:checkloop
tasklist /fi "imagename eq %PROCESS%" 2>nul | find /i "%PROCESS%" > nul
if %ERRORLEVEL%==0 (
  :: まだ実行中 → 5秒待って再チェック
  timeout /t 5 /nobreak > nul
  goto :checkloop
)

echo %PROCESS% が終了しました。

ネットワーク接続を待つ

wait-for-network.bat
@echo off
set HOST=google.com
set RETRY=0
set MAX_RETRY=30

echo ネットワーク接続を確認中...

:netcheck
ping -n 1 -w 1000 %HOST% > nul 2>&1
if %ERRORLEVEL%==0 (
  echo ネットワーク接続を確認できました。
  goto :connected
)

set /a RETRY+=1
if %RETRY% geq %MAX_RETRY% (
  echo ネットワーク接続に失敗しました。
  exit /b 1
)

echo 接続待ち... (%RETRY%/%MAX_RETRY%)
timeout /t 10 /nobreak > nul
goto :netcheck

:connected
echo オンライン処理を開始します。

PowerShell Start-Sleep との連携

より精密な待機(ミリ秒単位)が必要な場合は、バッチファイルから PowerShell を呼び出します。

秒単位の待機

ps-sleep.bat
@echo off
echo 5秒待機します...

:: PowerShellで5秒待機
powershell -command "Start-Sleep -Seconds 5"

echo 完了。

ミリ秒単位の待機

ps-sleep-ms.bat
@echo off
echo 500ミリ秒待機します...

:: PowerShellでミリ秒単位の待機
powershell -command "Start-Sleep -Milliseconds 500"

echo 完了。

注意:PowerShell の起動には数百ミリ秒〜1秒程度のオーバーヘッドがあります。短い待機を大量に繰り返す場合は、PowerShell スクリプト側でループする方が効率的です。

PowerShell で高度な待機処理

ps-advanced-wait.bat
@echo off
:: 特定のポートが開くまで待機(サーバー起動待ち)
powershell -command "while (-not (Test-NetConnection -ComputerName localhost -Port 8080 -InformationLevel Quiet -ErrorAction SilentlyContinue)) { Start-Sleep -Seconds 2; Write-Host 'ポート8080の応答を待っています...' }"

echo サーバーが起動しました。

WAITFOR コマンド(シグナル待機)

WAITFOR は、ネットワーク上のシグナル(信号)を送受信して、複数のマシン間でバッチ処理を同期するためのコマンドです。

基本構文

モード 構文 説明
受信(待機) WAITFOR シグナル名 シグナルが送られるまで待機
受信(タイムアウト付き) WAITFOR /t 秒数 シグナル名 指定秒数まで待機
送信 WAITFOR /si シグナル名 シグナルを送信

マシン間の同期例

waitfor-receive.bat(受信側:待機するマシン)
@echo off
echo バックアップ完了シグナルを待機中...

:: 600秒(10分)のタイムアウト付きで待機
waitfor /t 600 BackupDone

if %ERRORLEVEL%==0 (
  echo シグナルを受信しました。後続処理を開始します。
) else (
  echo タイムアウトしました。
  exit /b 1
)
waitfor-send.bat(送信側:処理が完了したマシン)
@echo off
echo バックアップ処理を実行中...

:: バックアップ処理...
xcopy "D:\data" "E:\backup\data" /s /e /y

:: 完了シグナルを送信
waitfor /si BackupDone
echo 完了シグナルを送信しました。

WAITFOR の用途

  • サーバー間でのバッチ処理の同期(バックアップ完了→集計開始など)
  • SQL Server のジョブ連携(データ投入完了→レポート生成)
  • 同一マシン上の別ウィンドウのバッチ間の同期
  • WAITFORWindows Pro/Enterprise で利用可能です(Home では使えない場合あり)

時刻指定での実行待ち

特定の時刻になるまで待機して処理を実行するパターンです。タスクスケジューラを使えない場合に便利です。

指定時刻まで待機するバッチ

wait-until-time.bat
@echo off
set TARGET_TIME=03:00

echo %TARGET_TIME% まで待機します...

:timecheck
:: 現在時刻を取得(HH:MM形式)
set CURRENT=%TIME:~0,5%

:: 先頭のスペースを0に置換(午前の時刻対策)
set CURRENT=%CURRENT: =0%

if "%CURRENT%"=="%TARGET_TIME%" (
  echo 指定時刻になりました。処理を開始します。
  goto :execute
)

:: 30秒ごとにチェック
timeout /t 30 /nobreak > nul
goto :timecheck

:execute
echo === 夜間バッチ処理を実行 ===
call nightbatch.bat

ポイント:定期実行には Windows のタスクスケジューラを使う方が確実です。この方法はタスクスケジューラが使えない環境や、一度だけの待機に適しています。

待機方法の比較

どの方法を使うべきかを判断するための比較表です。

方法 精度 中断 対応OS 主な用途
timeout 秒単位 キー / Ctrl+C Vista以降 一般的な時間待機
ping 約1秒単位 Ctrl+C 全バージョン レガシー環境
choice 秒単位 選択キー / タイムアウト Vista以降 ユーザー選択付き待機
START /WAIT プロセス依存 プロセス終了時 全バージョン 外部プログラム完了待ち
WAITFOR シグナル依存 タイムアウト / Ctrl+C Pro/Enterprise マシン間同期
PowerShell ミリ秒単位 Ctrl+C PS対応環境 高精度・複雑な待機
IF + GOTO ループ チェック間隔依存 Ctrl+C 全バージョン 条件付き待機全般

よくあるエラーと対処法

「’timeout’ は、内部コマンドまたは外部コマンド…として認識されていません」

原因 対処法
Windows XP 以前を使用 ping による待機に切り替える
PATH が通っていない フルパス %SystemRoot%\system32\timeout.exe を指定

「入力のリダイレクトがサポートされています」エラー

timeout をリダイレクト付きで使うと発生する場合があります。

エラーが出る場合と対処法
:: エラーが出る場合がある
timeout /t 5

:: 対処法1: /nobreak を付ける
timeout /t 5 /nobreak

:: 対処法2: 出力を nul にリダイレクト
timeout /t 5 /nobreak > nul

注意:このエラーは、timeout がタスクスケジューラやリモートから実行された際(標準入力がない場合)に発生しやすいです。/nobreak を付けることで回避できます。

待機が期待通りの秒数にならない

症状 原因 対処法
ping の待機が長い/短い ping の間隔が環境依存 timeout に切り替える
timeout が即終了する ユーザーがキーを押した /nobreak を付ける
PowerShell が遅い PS起動のオーバーヘッド PS内でループするか、timeout を使う

実務パターン集

パターン1:サービス起動待ち

Windows サービスが起動するまで待機してから後続処理を実行します。

wait-service.bat
@echo off
setlocal enabledelayedexpansion

set SERVICE=MySQL80
set MAX_WAIT=120
set ELAPSED=0

echo サービス「%SERVICE%」の起動を待機中...
net start %SERVICE% 2>nul

:svccheck
sc query %SERVICE% | find "RUNNING" > nul 2>&1
if %ERRORLEVEL%==0 (
  echo サービスが起動しました。
  goto :svcrunning
)

if !ELAPSED! geq %MAX_WAIT% (
  echo サービス起動タイムアウト(%MAX_WAIT%秒)
  exit /b 1
)

timeout /t 5 /nobreak > nul
set /a ELAPSED+=5
echo 起動待ち... !ELAPSED!/%MAX_WAIT%秒
goto :svccheck

:svcrunning
echo データベース操作を開始します。

パターン2:ファイル転送完了待ち

FTP やコピー処理で転送されたファイルの書き込み完了を確認してから処理します。

wait-transfer.bat
@echo off
setlocal enabledelayedexpansion

set FILE=C:\transfer\data.zip
set PREV_SIZE=0
set STABLE_COUNT=0

:: ファイルが存在するまで待つ
:waitfile
if not exist "%FILE%" (
  timeout /t 5 /nobreak > nul
  goto :waitfile
)

:: ファイルサイズが変化しなくなるまで待つ(転送完了判定)
:sizecheck
for %%A in ("%FILE%") do set CURR_SIZE=%%~zA

if !CURR_SIZE!==!PREV_SIZE! (
  set /a STABLE_COUNT+=1
) else (
  set STABLE_COUNT=0
)

set PREV_SIZE=!CURR_SIZE!

:: 3回連続でサイズ変化なし → 転送完了と判定
if !STABLE_COUNT! geq 3 (
  echo 転送完了を確認しました(サイズ: !CURR_SIZE! bytes)
  goto :process
)

timeout /t 5 /nobreak > nul
goto :sizecheck

:process
echo ファイル処理を開始します。

パターン3:リトライ付きバッチ処理

失敗時に待機してリトライする、実務で頻出のパターンです。

retry-pattern.bat
@echo off
setlocal enabledelayedexpansion

set MAX_RETRY=3
set RETRY_WAIT=30
set ATTEMPT=0

:retry
set /a ATTEMPT+=1
echo === 試行 !ATTEMPT!/%MAX_RETRY% ===

:: メインの処理を実行
call main-process.bat

if %ERRORLEVEL%==0 (
  echo 処理が正常に完了しました。
  exit /b 0
)

if !ATTEMPT! geq %MAX_RETRY% (
  echo 最大リトライ回数に到達しました。処理を中断します。
  exit /b 1
)

echo 処理に失敗しました。%RETRY_WAIT%秒後にリトライします...
timeout /t %RETRY_WAIT% /nobreak > nul
goto :retry

パターン4:デプロイ用待機テンプレート

サービス停止 → 待機 → ファイル配置 → サービス起動を順次実行するテンプレートです。

deploy-with-wait.bat
@echo off
setlocal enabledelayedexpansion

set SERVICE=MyAppService
set DEPLOY_DIR=C:\app
set SOURCE_DIR=C:\release

echo === Step 1: サービス停止 ===
net stop %SERVICE%
timeout /t 10 /nobreak > nul

:: プロセスが完全に終了するまで待機
:stopcheck
sc query %SERVICE% | find "STOPPED" > nul 2>&1
if %ERRORLEVEL% neq 0 (
  timeout /t 5 /nobreak > nul
  goto :stopcheck
)

echo === Step 2: ファイル配置 ===
xcopy "%SOURCE_DIR%\*" "%DEPLOY_DIR%\" /s /e /y

echo === Step 3: サービス起動 ===
net start %SERVICE%

:: 起動確認
timeout /t 5 /nobreak > nul
sc query %SERVICE% | find "RUNNING" > nul 2>&1
if %ERRORLEVEL%==0 (
  echo デプロイ完了。サービスは正常に稼働中です。
) else (
  echo 警告: サービスが起動していません。手動で確認してください。
  exit /b 1
)

まとめ

バッチファイルの待機方法 – 選び方ガイド

  • 単純な時間待機timeout /t 秒数 /nobreak(最も推奨)
  • レガシー環境ping 127.0.0.1 -n N > nul
  • ユーザー選択付きchoice /t 秒数 /d デフォルト
  • プログラム完了待ちSTART /WAIT プログラム名
  • ファイルや条件の待機IF + GOTO ループ(タイムアウト必須)
  • マシン間の同期WAITFOR シグナル名
  • ミリ秒精度が必要 → PowerShell Start-Sleep -Milliseconds

ポイント:実務ではタイムアウトを必ず設定してください。無限ループはバッチ処理の障害原因になります。また、自動実行バッチでは /nobreak を忘れずに付けましょう。

関連記事