バッチファイルで別のプログラムやバッチを実行するとき、CALL と START のどちらを使うか迷ったことはありませんか?「CALL は呼び出し元に戻る、START は新しいプロセスを起動する」という違いは知っていても、細かい挙動・オプション・使い分けを正確に把握している人は少ないです。本記事では両コマンドの違いを徹底比較し、実務での正しい使い分けを解説します。
この記事で学べること
- CALL と START の根本的な違い(同期 vs 非同期・ウィンドウ・ERRORLEVEL)
- START の全オプション(/B・/WAIT・/MIN・/MAX・/D・/LOW など)
- CALL の用途(バッチ呼び出し・サブルーチン・内部コマンド)
- どちらを使うべきか? 判断フローチャート
- 実務パターン(並列実行・GUI起動・戻り値取得・ファイルを開く)
一言で言うと:CALL は「往復」、START は「片道」
| 比較項目 | CALL | START |
|---|---|---|
| 実行の流れ | 同期(完了まで待つ) | 非同期(すぐ次へ進む)※デフォルト |
| 呼び出し元に戻る | 戻る | 戻らない(独立プロセス) |
| ERRORLEVEL 取得 | 取得できる | 取得できない(/WAIT でも不可) |
| 新規ウィンドウ | 開かない(同じコンテキスト) | 開く(/B で抑制可) |
| 内部コマンド呼び出し | 可能(CALL ECHO 等) | 不可(外部プロセスのみ) |
| サブルーチン(:ラベル) | 可能(CALL :Label) | 不可 |
| 環境変数の引き継ぎ | 親プロセスの環境を共有 | 親プロセスのコピーを新規作成 |
CALL の仕組みと用途
CALL は同じ cmd.exe の流れの中で別のバッチやサブルーチンを実行し、完了後に呼び出し元の次の行に戻ります。
用途1:別のバッチファイルを呼ぶ
@echo off CALL setup.bat if %ERRORLEVEL% NEQ 0 ( echo setup.bat が失敗しました EXIT /B 1 ) echo セットアップ完了、メイン処理へ
CALL なしで別バッチを実行すると戻ってこない
setup.bat(CALL なし)と書くと、setup.bat の処理が終わった後に呼び出し元のバッチに戻りません。
別バッチを呼んで処理を続けたい場合は必ず CALL を付けてください。
用途2:サブルーチン呼び出し
CALL :MyFunc "引数1" "引数2" :MyFunc echo %~1 / %~2 EXIT /B
用途3:内部コマンドの変数展開(遅延展開の回避)
:: 変数を展開してから SET を呼ぶ CALL SET NEWVAR=%%BASE_VAR:str1=str2%%
CALL のオプション
| 構文 | 説明 |
|---|---|
CALL file.bat |
別バッチを同期実行して戻る |
CALL file.bat arg1 arg2 |
引数付きで別バッチを呼ぶ |
CALL :Label |
同一バッチ内サブルーチン呼び出し |
CALL :Label arg1 |
引数付きサブルーチン呼び出し |
START の仕組みと用途
START は新しいプロセス(または新しいウィンドウ)を起動し、呼び出し元はすぐに次の行に進みます。GUI アプリの起動・並列処理・ファイルを関連付けアプリで開くときに使います。
START の全オプション一覧
| オプション | 意味 | 用途例 |
|---|---|---|
/B |
新規ウィンドウを開かずバックグラウンド実行 | 並列バッチ処理 |
/WAIT |
起動したプロセスの終了まで待つ | インストーラ完了待ち |
/MIN |
最小化で起動 | バックグラウンド処理を目立たせない |
/MAX |
最大化で起動 | 全画面表示が必要なアプリ |
/D パス |
作業ディレクトリを指定 | 特定フォルダで起動したいとき |
/LOW |
優先度:低 | バックグラウンドで邪魔しない処理 |
/NORMAL |
優先度:通常(デフォルト) | — |
/HIGH |
優先度:高 | リアルタイム性が必要な処理 |
/ABOVENORMAL |
優先度:通常より高い | — |
/BELOWNORMAL |
優先度:通常より低い | — |
/I |
新しい環境(起動時の初期値)で実行 | クリーンな環境で実行したい場合 |
用途1:GUI アプリを開く(非同期)
@echo off :: メモ帳を開いて即次の処理へ START notepad.exe "C:logs esult.txt" echo メモ帳を起動しました(バッチは続行)
用途2:ファイルを関連付けアプリで開く
:: PDF・Excel・画像など、拡張子に関連付けられたアプリで開く START "" "C: eportsmonthly.pdf" START "" "C:data esult.xlsx"
START でファイルパスを渡すときは空タイトル “” が必要
START "C:pathfile.pdf" と書くと "C:pathfile.pdf" がウィンドウタイトルとして解釈され、ファイルが開きません。
ファイルを開く場合は必ず先頭に空の "" を入れてください。
START "" "C:pathfile.pdf"
用途3:並列バッチ処理(/B)
@echo off echo 3つのバッチを並列実行... START /B process_a.bat START /B process_b.bat START /B process_c.bat echo すべて起動完了(完了は非同期)
用途4:インストーラを同期的に実行(/WAIT)
@echo off echo インストール中... START /WAIT "" "setup.exe" /silent echo インストール完了(setup.exe が終了した)
START /WAIT では ERRORLEVEL が取得できない
START /WAIT で待機しても、起動したプロセスの終了コードが ERRORLEVEL に反映されないケースがあります(プログラムによって異なります)。
終了コードを確実に取得したい場合は CALL を使ってください。
使い分け判断フロー
実行したい処理は?
├─ .bat ファイル
│ ├─ 完了を待って ERRORLEVEL を取得したい → CALL
│ ├─ 完了を待つが ERRORLEVEL は不要 → CALL(またはSTART /WAIT)
│ └─ バックグラウンドで並列実行したい → START /B
│
├─ .exe・インストーラ
│ ├─ 完了まで待って次に進みたい → START /WAIT "" "app.exe"
│ └─ 起動だけして次の処理を続けたい → START "" "app.exe"
│
└─ ファイルを関連アプリで開く
└─ 何でも → START "" "file.ext"
CALL vs START の動作比較(コード例)
例1:同期 vs 非同期の違い
@echo off echo === CALL(同期) === CALL ping -n 3 127.0.0.1 >nul echo ping 完了後にこの行が実行される echo === START(非同期) === START /B ping -n 3 127.0.0.1 >nul echo ping の完了を待たずにこの行が実行される
例2:ERRORLEVEL の取得可否
@echo off :: CALL → ERRORLEVEL 取得可 CALL myprocess.bat echo CALL後のERRORLEVEL: %ERRORLEVEL% :: START /WAIT → ERRORLEVEL 取得不確実 START /WAIT "" myprocess.bat echo START /WAIT後のERRORLEVEL: %ERRORLEVEL% :: ※ プログラムによって 0 固定になるケースがある
例3:環境変数の共有範囲
@echo off set MY_VAR=親バッチの値 :: CALL → 親の環境変数が子バッチに見える CALL child.bat :: child.bat 内で echo %MY_VAR% → 「親バッチの値」と表示される :: START → 親の環境変数のコピーが渡される(起動時点のスナップショット) START "" cmd /k echo %MY_VAR% :: 起動時点の MY_VAR が引き継がれるが、子での変更は親に影響しない
よく混乱するケース別まとめ
ケース1:別バッチを呼んで処理継続したい
| 書き方 | 動作 | 推奨 |
|---|---|---|
setup.bat(直接) |
setup.bat終了後に親バッチに戻らない | NG |
CALL setup.bat |
完了後に親バッチに戻る | ◯ |
START /B setup.bat |
非同期(完了を待たない)、ERRORLEVEL不可 | 並列なら可 |
ケース2:インストーラを起動して完了まで待ちたい
| 書き方 | 動作 | 推奨 |
|---|---|---|
CALL setup.exe /silent |
完了まで待つ、ERRORLEVEL取得可 | ◯ |
START /WAIT "" setup.exe /silent |
完了まで待つが、ERRORLEVEL不確実 | △(確認要) |
START "" setup.exe /silent |
非同期起動(待たない) | NG(完了確認不可) |
ケース3:ファイルをダブルクリックと同じ動作で開きたい
| 書き方 | 動作 | 推奨 |
|---|---|---|
START "" "report.pdf" |
関連付けアプリで開く | ◯ |
CALL "report.pdf" |
エラー(バッチ/exeでないため) | NG |
実務パターン4選
パターン1:複数バッチの逐次実行(CALL)
@echo off setlocal CALL :Log "INFO" "=== 処理開始 ===" CALL step1_backup.bat if %ERRORLEVEL% NEQ 0 CALL :Log "ERROR" "step1失敗" & EXIT /B 1 CALL step2_transfer.bat if %ERRORLEVEL% NEQ 0 CALL :Log "ERROR" "step2失敗" & EXIT /B 1 CALL step3_cleanup.bat CALL :Log "INFO" "=== 全処理完了 ===" EXIT /B 0 :Log echo [%DATE% %TIME:~0,8%] %~1: %~2 echo [%DATE% %TIME:~0,8%] %~1: %~2 >> run.log EXIT /B
パターン2:並列バッチ処理+完了待ち(START /B + ロックファイル方式)
並列処理の完了をロックファイルで管理する確実な方法です。tasklist で cmd.exe を待つ方法は無関係な別プロセスも引っかかるため、ロックファイル方式が実務での推奨です。
@echo off setlocal :: 先にロックファイルを作成 type nul > lock_a.tmp type nul > lock_b.tmp type nul > lock_c.tmp :: 各バッチを並列起動。完了したらロックファイルを削除 START /B cmd /c "process_a.bat & del lock_a.tmp" START /B cmd /c "process_b.bat & del lock_b.tmp" START /B cmd /c "process_c.bat & del lock_c.tmp" :: 全ロックファイルが消えるまでポーリング :WAIT_LOOP if exist lock_a.tmp ( timeout /T 1 /NOBREAK >/dev/null & GOTO :WAIT_LOOP ) if exist lock_b.tmp ( timeout /T 1 /NOBREAK >/dev/null & GOTO :WAIT_LOOP ) if exist lock_c.tmp ( timeout /T 1 /NOBREAK >/dev/null & GOTO :WAIT_LOOP ) echo 全並列処理完了
ロックファイル方式のポイント
各バッチが del lock_X.tmp を実行して完了を通知します。親バッチはファイルの有無をポーリングして全完了を検知します。大規模な並列制御が必要な場合は PowerShell の Start-Process -Wait も検討してください。
パターン3:GUI アプリを起動してレポートを開く(START)
@echo off setlocal set REPORT=C: eports\%DATE:~0,4%%DATE:~5,2%%DATE:~8,2%_report.xlsx :: レポート生成(バッチで処理) CALL generate_report.bat if %ERRORLEVEL% NEQ 0 ( echo レポート生成失敗 EXIT /B 1 ) :: 生成したExcelを開く if exist "%REPORT%" ( START "" "%REPORT%" echo レポートを開きました: %REPORT% )
パターン4:新規ウィンドウで処理を可視化(START /MIN /MAX)
@echo off :: 監視ログを別ウィンドウで tail 表示 START "ログ監視" /MIN cmd /k "tail -f C:logsapp.log 2>nul || more +1 C:logsapp.log" :: メイン処理 CALL main_process.bat :: 監視ウィンドウを閉じる taskkill /FI "WINDOWTITLE eq ログ監視" /F >nul 2>&1
よくある質問(FAQ)
❓ CALL と START /WAIT は何が違う? (クリックで開閉)
どちらも「完了まで待つ」動作ですが、決定的な違いがあります。
CALL:ERRORLEVEL を確実に取得できる。バッチ・サブルーチン・内部コマンドに使えるSTART /WAIT:新しいプロセスとして起動。ERRORLEVEL の取得はプログラム依存で不確実。主に .exe に使う
バッチファイルを呼ぶなら CALL、exe を呼んで完了待ちするなら START /WAIT か CALL を試して確認するのが実務上の判断基準です。
❓ START でバッチを呼ぶと ERRORLEVEL が取れない理由は? (クリックで開閉)
START は新しい cmd.exe プロセスを起動します。そのプロセスの終了コードは親の ERRORLEVEL に自動的に伝わりません。
CALL は同じ cmd.exe コンテキスト内で実行するため、EXIT /B で設定した ERRORLEVEL が呼び出し元に正しく伝わります。
❓ START “” のダブルクォートは何のため? (クリックで開閉)
START コマンドの最初の文字列はウィンドウタイトルとして解釈されます。
START "C:\path\file.pdf" と書くと C:\path\file.pdf がタイトルになり、ファイルが開きません。
空の "" を入れてタイトルをなしにすることで、次の引数がコマンドとして正しく処理されます。
❓ バッチを CALL なしで直接呼ぶとどうなる? (クリックで開閉)
呼び出したバッチの処理が終わると、呼び出し元のバッチには戻りません。cmd.exe のセッションが終了するか、呼び出したバッチが GOTO :EOF でファイル末尾に達した時点で止まります。
意図的に「このバッチに処理を引き継ぐ」場合以外は、常に CALL を使ってください。
❓ START /B と START の違いは? (クリックで開閉)
START(/B なし)は新しいコンソールウィンドウを開いて実行します。
START /B は新しいウィンドウを開かず、同じコンソール内でバックグラウンド実行します。
並列バッチ処理では START /B が一般的です。複数ウィンドウを開いてユーザーに進捗を見せたい場合は START(/B なし)を使います。
まとめ
| 状況 | 推奨コマンド | 理由 |
|---|---|---|
| 別バッチを呼んで結果を受け取る | CALL file.bat |
ERRORLEVEL 確実に取得できる |
| 同一バッチ内のサブルーチン | CALL :Label |
引数渡し・戻り値・再帰が可能 |
| 複数バッチを並列実行 | START /B cmd /c file.bat |
非同期で同時起動 |
| .exe を待って完了確認 | START /WAIT "" app.exe(または CALL app.exe) |
ERRORLEVEL の取得はプログラム依存。GUIアプリは START /WAIT を推奨 |
| ファイルを関連アプリで開く | START "" "file.ext" |
CALL では開けない(exe でないため) |
| GUI アプリをバックグラウンド起動 | START /MIN "" "app.exe" |
最小化で起動、バッチは続行 |
「戻り値が必要なら CALL、独立して動かすなら START」という原則を覚えれば、ほとんどのケースで正しい判断ができます。迷ったときは上記の判断フローとまとめ表を参考にしてください。
