バッチファイルの起動時にパラメータ(コマンドライン引数)を渡すには、下記のように空白で区切って値を入力します。
C:\> sample.bat AAA BBB CCC
バッチファイルの中でコマンドライン引数を参照するには、%1
、%2
、%3
といった特殊な変数を参照します。
%0
には、起動したバッチファイル名が格納されています(上記の例では sample.bat
)。
下記のバッチファイルは、3 つのコマンドライン引数の値を表示します。
先頭の @echo off
は、その後に実行するコマンドを画面上に表示しないようにするおまじないです。
@echo off
echo %1
echo %2
echo %3
C:\> sample AAA BBB CCC
AAA
BBB
CCC
指定するパラメータの数が足りない場合、echo
コマンドがパラメータなしで実行されてしまうことに注意してください。
C:\> sample AAA
AAA
ECHO は <OFF> です。
ECHO は <OFF> です。
パラメータとして渡したい文字列が空白を含んでいる場合は、その文字列全体をダブルクォーテーションで囲みます。
C:\> sample "AAA 1" "BBB 2" "CCC 3"
"AAA 1"
"BBB 2"
"CCC 3"
ただし、この場合は引用符も上記のようにそのまま出力されてしまうことに注意してください。
%1
と参照している部分を、%~1
という参照方法に変えると、引用符を削除して出力することができます。
@echo off
echo %~1
echo %~2
echo %~3
C:\> sample "AAA 1" "BBB 2" "CCC 3"
AAA 1
BBB 2
CCC 3
このような特殊な引数展開には、他にもいろいろな方法が用意されています。
コマンドシェル上で、call /?
と実行すると、下記のようなヘルプを見ることができます。
バッチ パラメーター (%n) の置換は拡張されました。次のオプション構文
を使うことができます:
%~1 - すべての引用句 (") を削除して、%1 を展開します。
%~f1 - %1 を完全修飾パス名に展開します。
%~d1 - %1 をドライブ文字だけに展開します。
%~p1 - %1 をパスだけに展開します。
%~n1 - %1 をファイル名だけに展開します。
%~x1 - %1 をファイル拡張子だけに展開します。
%~s1 - 展開されたパスは、短い名前だけを含みます。
%~a1 - %1 をファイル属性に展開します。
%~t1 - %1 をファイルの日付/時刻に展開します。
%~z1 - %1 をファイルのサイズに展開します。
%~$PATH:1 - PATH 環境変数に指定されているディレクトリを検索し、
最初に見つかった完全修飾名に %1 を展開します。
環境変数名が定義されていない場合、または
検索してもファイルが見つからなかった場合は、
この修飾子を指定すると空の文字列に展開されます。
修飾子を組み合わせて、複合結果を得ることもできます:
%~dp1 - %1 をドライブ文字とパスだけに展開します。
%~nx1 - %1 をファイル名と拡張子だけに展開します。
%~dp$PATH:1 - PATH 環境変数に指定されているディレクトリを
検索して %1 を探し、最初に見つかったファイル
のドライブ文字とパスだけに展開します。
%~ftza1 - %1 を DIR の出力行のように展開します。
下記のようにすると、任意の位置のコマンドライン引数が渡されたか(渡されていないか)を調べることができます。
if not "%~1"=="" (
echo %1
)
あるいは、neq
を使って下記のようにも書けます。
if "%~1" neq "" (
echo %1
)
neq
は本来は数値を含むかもしれない文字列の比較のために使われる演算子ですが、ここでは空かどうかの比較をしているだけなので、うまく動作します。
if "%~1"=="" (
echo Need a parameter
exit /b
)
条件式の中で、%1
と参照するのではなく、%~1
と参照しているのは、引用符で囲まれたパラメータを渡された場合に、シンタックスエラーになるのを防ぐためです。
まぁ、こう書くべきなのだと覚えておけば大丈夫です。
ちなみに、exit /b
はコマンドシェルごと終了せずに、バッチファイルだけを終了する命令です。
Linux のシェルスクリプトでは、$#
でコマンドライン引数の数を調べることができますが、Windows のバッチファイルにはこのような仕組みはありません。
代わりに、n 個のパラメータが渡されたかどうかを調べるためには、n 番目のパラメータの値が空でないかを確認します。
if "%~3"=="" (
echo Need at least 3 parameters
exit /b
)
バッチファイルに渡されたすべてのパラメータは、%*
という特殊な変数で、まとめて 1 つの文字列として参照することができます。
パラメータを 1 つずつ参照する方法では、%1
~%9
の 9 個までしか対応できないので、10 個以上のパラメータを使用する場合は、この %*
を使用するしかありません(そんなケースはレアでしょうけど)。
下記の例では、for
ループを使って、コマンドライン引数を 1 つずつ取り出しながらループ処理しています。
@echo off
FOR %%a IN (%*) DO echo %%a
ここでは、ループ変数に %%a
を使っていますが、%%a
~ %%z
の記号を使用することができます(小文字・大文字は区別されません)。
C:\> sample AAA BBB CCC
AAA
BBB
CCC
空白を含むパラメータを渡したい場合にダブルクォーテーションで囲む必要があるのはこれまでと同様です。
C:\> sample "AAA BBB" CCC
"AAA BBB"
CCC
展開時に前後の引用符を削除するには、%%a
と参照している部分を %%~a
に変更します。
ちょっと特殊なやり方ですが、shift
コマンドを使ってコマンドライン引数をループ処理する方法もあります。
shift
コマンドを実行すると、%*
に含まれている先頭の引数が削除(シフト)されます。
その結果、%1
が 2 番目のパラメータを参照するようになります。
これを繰り返すことで、すべてのコマンドライン引数をループ処理できます。
@echo off
:LOOP
if not "%~1"=="" (
echo %~1
shift
goto LOOP
)
バッチファイルには while ループは存在しないので、仕方なく goto
を使って LOOP
ラベルへジャンプしています。
気持ち悪いコードですね。
ループ処理はできるだけ FOR
を使って記述しましょう。
下記のバッチファイルは、パラメータが指定されていない場合に、使用方法 (Usage) を出力して終了します。 テンプレートとしてお使いください。
@echo off
setlocal
if "%~1"=="" (goto USAGE)
echo Hello, %~1.
echo I am Maku.
exit /b
:USAGE
echo Usage: %~n0 YOUR_NAME
%~n0
はディレクトリ名を除いたバッチファイル名に変換されます。
C:\> hello
Usage: hello YOUR_NAME
C:\> hello Jack
Hello, Jack.
I am Maku.
下記のバッチファイルは、パラメータが省略された場合に、デフォルトの値(ここでは 100)を使って動作します。 テンプレートとしてお使いください。
@echo off
setlocal
set AGE=%~1
if "%AGE%"=="" (set AGE=100)
echo You are %AGE% years old
C:\> age
You are 100 years old
C:\> age 14
You are 14 years old