目次
結論
正常終了以外を検知したい場合、for文の中では、
if ERRORLEVEL 1 (
処理
)
を使いましょう。
forループでの挙動
簡単に言うと、forループ内の命令で正常終了しなかった場合でも、%ERRORLEVEL%の値が変わるのはループを抜けた後なので、for文内で%ERRORLEVEL%との大小比較では、欲しい挙動を示してくれないということです。
実際に挙動を比較してみましょう。2通りのバッチファイルを用意します。
1つ目は、for文の中で %ERRORLEVEL% と数値を比較することによって、正常終了しているかどうかを判別するバッチファイルです。
@echo off
rem 正常終了する命令で ERRORLEVEL を 0 に
python --version
echo before loop ERRORLEVEL: %ERRORLEVEL%
for %%i in (*.py) do (
python %%i
echo %%i ERRORLEVEL: %ERRORLEVEL%
if %ERRORLEVEL% neq 0 (
exit /b
)
)
echo after loop ERRORLEVEL: %ERRORLEVEL%
echo finish
2つ目は、for文の中で if文の ERRORLEVEL を用いた特殊(?)な文法を用いることによって、正常終了しているかどうかを判別するバッチファイルです
@echo off
rem 正常終了する命令で ERRORLEVEL を 0 に
python --version
echo before loop ERRORLEVEL: %ERRORLEVEL%
for %%i in (*.py) do (
python %%i
echo %%i ERRORLEVEL: %ERRORLEVEL%
if ERRORLEVEL 1 (
exit /b
)
)
echo after loop ERRORLEVEL: %ERRORLEVEL%
echo finish
また、終了ステータス1を返してくれる以下のようなPythonファイルを複数用意します。
import sys
sys.exit(1)
試してみるディレクトリの中身は、以下のようになります。
test
├─── error1.py
├─── error2.py
├─── error3.py
├─── error4.py
├─── error5.py
├─── error6.py
├─── error7.py
├─── error8.py
├─── error9.py
├─── test1.bat
├─── test2.bat
└─── (test3.bat)
準備が整ったところで、早速ですが実行してみましょう。
1つ目のバッチファイルについて、実行結果は以下の通りになりました。
test>test1.bat
Python 3.9.5
before loop ERRORLEVEL: 0
error1.py ERRORLEVEL: 0
error2.py ERRORLEVEL: 0
error3.py ERRORLEVEL: 0
error4.py ERRORLEVEL: 0
error5.py ERRORLEVEL: 0
error6.py ERRORLEVEL: 0
error7.py ERRORLEVEL: 0
error8.py ERRORLEVEL: 0
error9.py ERRORLEVEL: 0
after loop ERRORLEVEL: 1
finish
pythonプログラムを実行した結果、終了コード1が返されており、%ERRORLEVEL% も1となってループを抜けてほしいのですが、最後まで走り切ってしまっている様子が見て取れます。また、for文から出ると、%ERRORLEVEL% が1となっていることが分かります。
次に、2つ目のバッチファイルについて、実行結果は以下の通りになりました。
test>test2.bat
Python 3.9.5
before loop ERRORLEVEL: 0
error1.py ERRORLEVEL: 0
for文中で %ERRORLEVEL% を表示させても 0 のままとなってしまっていますが、ERRORLEVEL を用いた分岐処理自体はうまくいっていることが分かります。
さらに、次のようなバッチファイルを実行してみましょう。
@echo off
rem ERRORLEVEL を 1 に
python error1.py
echo before loop ERRORLEVEL: %ERRORLEVEL%
for /l %%i in (1, 1, 9) do (
python --version
echo count %%i ERRORLEVEL: %ERRORLEVEL%
if ERRORLEVEL 1 (
exit /b
)
)
echo after loop ERRORLEVEL: %ERRORLEVEL%
echo finish
これを実行すると、次のような実行結果が得られます。
test>test3.bat
before loop ERRORLEVEL: 1
Python 3.9.5
count 1 ERRORLEVEL: 1
Python 3.9.5
count 2 ERRORLEVEL: 1
Python 3.9.5
count 3 ERRORLEVEL: 1
Python 3.9.5
count 4 ERRORLEVEL: 1
Python 3.9.5
count 5 ERRORLEVEL: 1
Python 3.9.5
count 6 ERRORLEVEL: 1
Python 3.9.5
count 7 ERRORLEVEL: 1
Python 3.9.5
count 8 ERRORLEVEL: 1
Python 3.9.5
count 9 ERRORLEVEL: 1
after loop ERRORLEVEL: 0
finish
forループ中では正常終了する命令を実行した場合でも、forループに入る直前で正常終了しない命令を実行してしまうと、こちらも正しくない結果が得られてしまうことも分かります。
以上のように、forループ中での %ERRORLEVEL% の値は、forループに入る直前の %ERRORLEVEL% の値で固定されてしまうので、分岐処理を書く際には気を付けましょう。