19
26

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

返り値をバッチファイルで受け取るときの注意点

Posted at

バッチファイル内であるアプリケーションの戻り値(返り値)を取得したい場合は
そのアプリケーションを実行した後%ERRORLEVEL%で取得できる

仮に 何かファイルを渡して、処理が成功すれば0が返り、失敗すれば1が返るhoge.exeというのがあったとして

call hoge.exe piyo.txt
if %ERRORLEVEL% == 1 @echo ダメです。

という感じで条件分岐だって可能だし

さてさてこれを利用して大量の処理をしたくなったとき(ってかバッチ処理ってそんなもの)

for %%f in (*.txt) do (
call hoge.exe %%f
if %ERRORLEVEL% == 1 @echo %%f:ダメです。>> log.log
)

的なことをやろうとして、思ったような結果が得られず、(この場合はERRORLEVELがいつまでたっても0のまま)えらい難儀している人はたくさんいると思う。

setlocal
(コマンド文)
endlocal

で挟んでやっても・・・・どうにもうまくいきません。

どうやらこれはバッチファイルの中にインタプリタ(?)する過程で、for doループがあると、そのブロック内は一度に評価される。 
そのため「%ERRORLEVEL%ほにゃらら」 は、その時点での値がそのまま埋め込まれて実行されるからだとか・・・(少々間違った解釈かも知れんが、とにかくこのままでは動的な変数のごとく使えないってことだ)

これを「環境変数の即時展開」というものらしい
じゃあ、環境変数を動的に扱いたい場合どうすればいいのか
その解決策は「環境変数の遅延展開」と呼ばれるもの
つまりsetlocalenabledelayedexpansionのオプションをつけてやる

長いですね

遅延:delayed
展開:expansion
有効:enable

具体的には
setlocal enabledelayedexpansionから始まってendlocalまでの間はこれが有効となる。
さらにこの中では環境変数の呼び出し方を%ではなく!で挟むようにしてやればOK
使用例としては

setlocal enabledelayedexpansion
for %%f in (*.txt) do (
  call hoge.exe %%f
  if !ERRORLEVEL! == 1 @echo %%f:ダメです。>> log.log
  if !ERRORLEVEL! == 0 @echo %%f:OKです。>> log.log
)
endlocal

初心者(中級者でも)が大ハマリするパターンだろう、
「どう考えても動くバッチに見えて仕方がないのに何で思うように動かないのか・・・・・・」
一度は苦労する点であることには間違いない、
別ブログに掲載していた記事をQiitaに掲載

19
26
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
26

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?