【bat】CALL と START の違いを完全解説|同期・非同期・ERRORLEVEL・ウィンドウ制御・使い分けガイド

バッチファイルで別のプログラムやバッチを実行するとき、CALLSTART のどちらを使うか迷ったことはありませんか?「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 + ロックファイル方式)

並列処理の完了をロックファイルで管理する確実な方法です。tasklistcmd.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 /WAITCALL を試して確認するのが実務上の判断基準です。

❓ 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」という原則を覚えれば、ほとんどのケースで正しい判断ができます。迷ったときは上記の判断フローとまとめ表を参考にしてください。