バッチファイルで他のバッチファイルの戻り値を利用する


Y子です。
いろいろバッチファイルを作っていますが、同じような処理をいくつものファイルに書くのは、書くのも読むのもしんどい気がしてきました。
一話完結の記事にするために1つのバッチファイルにまとめ、とは言え再利用しやすくするためにサブルーチン化し、結局は1つのバッチファイルが大きくなる、というジレンマを、最近のわたしは感じていました。

そこで今回は、1ファイルのコード量を減らす目的も兼ねて、処理を複数のバッチファイルに分け、戻り値として値をやり取りする方法を考えます。

概要

バッチファイルから別のバッチファイルを実行し、その実行結果を戻り値として受け取る方法を比較します。
確認環境:Windows 10 Home (Bld. 19042.928)

コード

(1) 呼び出される側(errorlevel)

まず、呼び出される側を2種類作ってみます。
引数を与えると、それをそのまま返すという簡単な処理です。

1つ目は、errorlevelとして戻り値を返すタイプ。
本来「終了コード」として使われる環境変数を、バッチファイルの戻り値に流用する手法です。
この手法は、いろいろなサイトで紹介されていました。

exit /bに続けて値を書いて終了すると、呼び出し側は%errorlevel%で受け取れます。

return_result1.bat
@echo off

setlocal
set arg=%~1
exit /b %arg%
endlocal

(2) 呼び出される側(標準出力)

2つ目は、標準出力で戻り値を返すタイプ。

単純にechoコマンドで値を出力します。

return_result2.bat
@echo off

setlocal
set arg=%~1
echo %arg%
endlocal

(3) 呼び出す側

前述の(1)(2)に同じ引数を渡し、戻り値を受け取って出力するバッチファイルです。
同じ値に対して、それぞれどのようにふるまうのか、比較できるようにします。

call_bat.bat
@echo off

setlocal
set arg=%~1

rem 戻り値をerrorlevelで取得
call return_result1.bat %arg%
echo 結果1:%errorlevel%

rem 戻り値をバッチの標準出力から取得
for /f "usebackq" %%a in (`call return_result2.bat %arg%`) do set result=%%a
echo 結果2:%result%

endlocal

実行結果

まずは数字を与えた場合。
どちらの処理も、与えた数字をそのまま取得できるようです。

実行結果(数字を与えた場合)
> call_bat.bat 1
結果1:1
結果2:1

> call_bat.bat 1234567890
結果1:1234567890
結果2:1234567890

次に、文字を与えた場合。
errorlevelを使う方は、「0」に変わってしまいました。
「終了コード」なので、数字しか戻せないように見えます。
標準出力の方は、問題なく戻り値を取得できました。

実行結果(文字を与え場合)
> call_bat.bat a
結果1:0
結果2:a

> call_bat.bat abcdefghij
結果1:0
結果2:abcdefghij

ためしに、文字数字交じりも与えてみます。
標準出力の方は、こちらも問題なさそうです。
errorlevelを使う方は、文字が出てくるとその後が捨てられてしまうようです。

実行結果(文字数字交じりを与え場合)
> call_bat.bat 123abc
結果1:123
結果2:123abc

> call_bat.bat abc123
結果1:0
結果2:abc123

> call_bat.bat 1a2b3c
結果1:1
結果2:1a2b3c

おわりに

「戻り値は数字に限る」なんて制約は、無い方がいいですもんね。
errorlevelは使い勝手が悪いので、echoの出力を受け取る方法の出番が多そうです。

前回のFIND関数は、今後ほかのバッチファイルから呼びたい機能です。
見やすさのために「2 文字目」なんて出力にしてしまいましたが、値を他の機能で使うことを考えると、「2」だけにしとけばよかったですね。

では!