5.関数/サブルーチン (4)コマンド、バッチの復帰値 〜コマンドが正常終了したか確認したい〜 【コマンドプロンプト、バッチファイルを使わなきゃならなくなった人向けのメモ】


コマンド、バッチファイルの復帰値を確認したい


%ERRORLEVEL%を参照する


正常の場合は0
異常の場合は1〜255
ただし、コマンドによっては常に0を返すものもある。

正常の例

D:\MyDoc\work\#blog\test>dir
 ドライブ D のボリューム ラベルは データ です
 ボリューム シリアル番号は 94BB-7973 です

 D:\MyDoc\work\#blog\test のディレクトリ

2009/10/14  07:21    <DIR>          .
2009/10/14  07:21    <DIR>          ..
2009/10/14  07:21                 0 test.txt
               1 個のファイル                   0 バイト
               2 個のディレクトリ  323,922,767,872 バイトの空き領域

D:\MyDoc\work\#blog\test>echo %ERRORLEVEL%
0

異常の例1

D:\MyDoc\work\#blog\test>dir notexistfile
 ドライブ D のボリューム ラベルは データ です
 ボリューム シリアル番号は 94BB-7973 です

 D:\MyDoc\work\#blog\test のディレクトリ

ファイルが見つかりません

D:\MyDoc\work\#blog\test>echo %ERRORLEVEL%
1

異常の例2

D:\MyDoc\work\#blog\test>notexistcommand
'notexistcommand' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。

D:\MyDoc\work\#blog\test>echo %ERRORLEVEL%
9009




関連あるかもしれない記事


バッチファイルのパラメータ

%0はバッチファイルのファイル名となる。

C言語と同じ。Javaをやってる人は違和感があるかも。
arg1.bat

@echo off
echo %0
D:\MyDoc\work\#blog\コマンドプロンプト>arg1.bat
arg1.bat

バッチファイルで使用できるパラーメータは%0〜%9まで

arg2.bat

@echo off
echo %1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11

%10は使えないので、%1と0の文字列と解釈されてしまう。
(コマンドパラメータが1〜11だと気づかないw)

D:\MyDoc\work\#blog\コマンドプロンプト>arg2.bat a b c d e f g h i j k 
a b c d e f g h i a0 a1

10個以上パラメータを使いたい場合

%*を使用することで全部表示することはできる。
arg3.bat

echo %*
D:\MyDoc\work\#blog\コマンドプロンプト>arg3.bat a b c d e f g h i j k
a b c d e f g h i j k

%*で表示できるけど・・・
いや、そうじゃなくて個別に10個以上パラメータを使いたいたいんだよ

個別に10個以上パラメータを使いたい場合

この場合は、shiftを使ってコマンドパラメータをずらしていく

arg4.bat

:top
if {%1}=={} goto :EOF
echo %1
shift
goto :top
D:\MyDoc\work\#blog\コマンドプロンプト>arg4.bat a b c d e f g h i j k
a
b
c
d
e
f
g
h
i
j
k


5.関数/サブルーチン (1)バッチファイルの呼び出し 〜体育館の裏に呼び出されました。。。〜 【コマンドプロンプト、バッチファイルを使わなきゃならなくなった人向けのメモ】


goto文ばかり使っていると訳分からなくなるので、バッチファイルを分割する。
その場合、バッチからバッチファイルを呼び出すときにはcall文を使用する。


呼び出すバッチファイルと呼び出されるバッチファイルが同じディレクトリにある場合は、ファイル名だけで
呼び出される。
拡張子は、あってもなくてもいいが、何を呼び出してるかを区別するために拡張子は書いた方がいいだろう。
カレントディレクトリにない場合は、環境変数PATHに設定すれば、ファイル名だけで呼び出される。
PATHにも設置されていない場合は、絶対パスで呼び出す。


拡張子を省略できるのは環境変数PATHEXTに設定されているものである。

D:\MyDoc\work\#blog\コマンドプロンプト\call\familyA>set pathext
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH

実行環境

ディレクトリ構成
D:\MyDoc\work\#blog\コマンドプロンプト\call>tree /F
省略
├─familyA
│      child1.bat
│      child2.CMD
│      parent.bat
│
├─familyB
│      cousin.bat
│
└─familyC
        friend.bat
各バッチの内容
call child1.bat
call child1
call child2.cmd
call child2
call cousin.bat
call D:\MyDoc\work\#blog\コマンドプロンプト\call\familyC\friend.bat
  • child1.bat
@echo 私は子供です。長男です。
  • child2.CMD
@echo 私は子供です。次男です。
  • cousin.bat
@echo 私はいとこです。
  • friend.bat
@echo 私は友達です。
環境変数
Path=C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;D:\MyDoc\work\#blog\コマンドプロンプト\call\familyB

実行結果

D:\MyDoc\work\#blog\コマンドプロンプト\call\familyA>parent.bat

D:\MyDoc\work\#blog\コマンドプロンプト\call\familyA>call child1.bat
私は子供です。長男です。

D:\MyDoc\work\#blog\コマンドプロンプト\call\familyA>call child1
私は子供です。長男です。

D:\MyDoc\work\#blog\コマンドプロンプト\call\familyA>call child2.cmd
私は子供です。次男です。

D:\MyDoc\work\#blog\コマンドプロンプト\call\familyA>call child2
私は子供です。次男です。

D:\MyDoc\work\#blog\コマンドプロンプト\call\familyA>call cousin.bat
私はいとこです。

D:\MyDoc\work\#blog\コマンドプロンプト\call\familyA>call D:\MyDoc\work\#blog\コマンドプロンプト\call\familyC\friend.bat
私は友達です。




関連あるかもしれない記事


4.基本文法 (4)forでループ処理 〜回って回って回るぅ〜 【コマンドプロンプト、バッチファイルを使わなきゃならなくなった人向けのメモ】


if文とgoto文を使わず、for文を使うことができる

c:\>for /L %i in (0,1,9) do @echo %i
0
1
2
3
4
5
6
7
8
9


バッチファイルを作成するときは、%iではなく%%iにする必要がある。

for /L %%i in (0,1,9) do @echo %%i




関連あるかもしれない記事

4.基本文法 (3)ループ処理〜もう一度最初から始めるんです。 もう一度。 もう一度。〜 【コマンドプロンプト、バッチファイルを使わなきゃならなくなった人向けのメモ】

指定回数分繰り返す、こういうことが1番コンピュータにやって欲しいことだろう。
サクッとバッチファイルを作成したいものだ。


if文とgoto文を組み合わせて使う。
悪名高きgoto文、指定したラベルに移動するもの。
goto文を乱用するとあっちゃこっちゃに移動してわけわからなくなるので注意。

バッチファイル

@echo off
setlocal
if {%1}=={} goto USAGE
set /A count=0
:TOP
if %count% GEQ %1 goto END
echo %count%


REM 繰り返し実行したい処理

set /A count=%count%+1
goto :TOP

:USAGE
echo 回数を指定してください
endlocal
:END


比較演算子の意味は以下。

  • EQU:等しい
  • NEQ:等しくない
  • LSS:より小さい
  • LEQ:以下
  • GTR:より大きい
  • GEQ:以上

4.基本文法 (2)if文の注意事項 〜\Microsoft の使い方が誤っています。〜 【コマンドプロンプト、バッチファイルを使わなきゃならなくなった人向けのメモ】

通常は以下の書き方が多いと思う。

IF "%ARG1%"=="%ARG2%"

しかしこの場合値に 「"」が含まれるとエラーになってしまう。

例えば、バッチのパラメータに空白を含むディレクトリを
指定するために、「"」「"」(ダブルクォート)でくくった場合など。


なので以下のように書くようにしている。

  IF {%ARG1%}=={%ARG2%} 
NGなパターンのバッチファイル
IF "%1"=="%2" (
  echo equal.
) ELSE (
  echo not equal.
)

%1,%2はコマンドパラーメターを表す特別な変数

NGなパターンの実行結果
c:\>D:\MyDoc\work\#blog\コマンドプロンプト\if-error.bat "C:\Documents and Settings\orangeclover" "C:\Documents and Settings\orangeclover"
and の使い方が誤っています。

c:\>IF ""C:\Documents and Settings\orangeclover""==""C:\Documents and Settings\orangeclover"" (
OKなパターンのバッチファイル
IF {%1}=={%2} (
  echo equal.
) ELSE (
  echo not equal.
)
OKなパターンの実行結果
c:\>D:\MyDoc\work\#blog\コマンドプロンプト\if-{}.bat "C:\Documents and Settings\orangeclover" "C:\Documents and Settings\orangeclover"

c:\>IF {"C:\Documents and Settings\orangeclover"} == {"C:\Documents and Settings\orangeclover"} (echo equal. )  ELSE (echo not equal. )
equal.


「{」「}」の代わりに「'」「'」でくくる手もあるが、'09などのディレクトリもよくある。
「{」「}」もディレクトリ名に使えるのので完全ではないが、「"」「"」と「 '」「'」よりかは
「{」「}」の方が確立が低いと思う。


しかし、これでも罠が残っていた。
Windows Server 2003 x64版でテスト用にPATHを設定しようと以下のようなバッチを
組んでいた。



if {%1} == {%2} (
    setlocal
    set PATH=%NORMAL_TEST_HOME%\bin;%PATH%
    endlocal
) else (
    set PATH=%ERROR_TEST_HOME%\bin;%PATH%
)

これが動かないのである。

Microsoft の使い方が誤っています。

なんじゃそりゃ

C:\>test.bat a b
\Microsoft の使い方が誤っています。

C:\>test.bat a a
\Microsoft の使い方が誤っています。


x64版だと32bitモジュールはC:\Program Files (x86)に含まれるている。
そのため環境変数が以下のようになっている

C:\>set PATH=C:\Program Files (x86)\Microsoft Visual Studio 8\VC\BIN\amd64;C:\Program Files (x86)\Mi
crosoft Visual Studio 8\VC\PlatformSDK\bin\win64\amd64;C:\Program Files (x86)\Microsoft Visual Studi
〜省略〜

そうするとPATHに含まれている「(」「)」を誤認してしまうのだ。。。

回避として、IF文を2つにしたけど。。。


エラーにある通りだ。

「(」「)」を含むディレクトリをデフォルトにして、set PATHができないなんて
ホント 「Microsoft の使い方が誤っています。」だよ。







関連あるかもしれない記事

4.基本文法 (1)if文、else文 〜もしもー、それ以外ならばー〜 【コマンドプロンプト、バッチファイルを使わなきゃならなくなった人向けのメモ】


if文とelse文
else文ももちろん使える。
しばらく使えないと思い込んでた。
ifのヘルプにきっちり書いてあるんだよね。。。

以下の環境変数を設定してることを前提。
set ARG1=A
set ARG2=A

正しい使い方1

if-else-normal1.bat
IF {%ARG1%}=={%ARG2%} (
  echo equal.
) ELSE (
  echo not equal.
)
実行結果
D:\MyDoc\work\#blog\コマンドプロンプト>IF {A} == {A} (echo equal. )  ELSE (echo not equal. )
equal.

実行時には正しい使い方2と同じに解釈される。
でも、この書き方の方が読みやすいので、こちらを使った方がよい。

正しい使い方2

if-else-normal2.bat
IF {%ARG1%}=={%ARG2%} (echo equal.) ELSE (echo not equal.)
実行結果
D:\MyDoc\work\#blog\コマンドプロンプト>IF {A} == {A} (echo eqlual. )  ELSE (echo not equal. )
eqlual.

実行するコマンドを()で囲むのがポイント

誤った使い方1

if-else-error1.bat
IF {%ARG1%}=={%ARG2%} echo equal. ELSE echo not equal.
実行結果
D:\MyDoc\work\#blog\コマンドプロンプト>IF {A} == {A} echo eqlual. ELSE echo not equal.
eqlual. ELSE echo not equal.

ヘルプには以下の説明がある。

del コマンドは、改行で終了しなければならないため、次の例は、正しく動作し
ません:

delだけでなく、コマンドは、改行で終わるまでをパラメータとして認識してしまうから
ELSE以降もコマンドパラメータとして認識されてしまっている。

誤った使い方2

if-else-error2.bat
IF {%ARG1%}=={%ARG2%} echo equal.
ELSE echo not equal.
実行結果
D:\MyDoc\work\#blog\コマンドプロンプト>ELSE echo not equal.
'ELSE' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。

ELSEをコマンドとして認識してしまっているのでNG
ifはコマンドだがelseは節(ifのコマンドオプション)なので誤解しやすい

入れ子も可能

set /A TEST1=%random%/10000
set /A TEST2=%random%/10000

IF {%TEST1%}=={1} (
  IF {%TEST2%}=={2} (
     echo TEST1=1,TEST2=2
  ) ELSE (
     echo TEST1=1,TEST2!=2
  )
) ELSE (
  IF {%TEST2%}=={2} (
    echo TEST1!=1,TEST2=2
  ) ELSE (
    echo TEST1!=1,TEST2!=2
  )
)


Windows コマンドプロンプト ポケットリファレンス
4774149543