Windows バッチファイル (.bat や .cmd) を実行するときに、パラメーターを指定して引数を渡したいと思ったのでおいておきます。 これまで面倒で考えてなかったのですが、便利。
tl;dr;
- シェルスクリプトと同じように引数を組めるので、Windowsバッチだからパラメーター入力できないとあきらめる必要はありません。(過去の自分へ)
- 複数のパラメーターをユーザーが選択して指定できるようにしたい、こういったときにパラメーター入力は便利です
- 引数解析も単純なので定番として利用できます
gist においておきます。
https://gist.github.com/guitarrapc/a6c3fc433e7f98ef74f6cb45f4f2a952
どういうことをしたいのか
イメージしやすいように シェルスクリプト (Bash) や PowerShell で考えてみましょう。
シェルスクリプトを利用するときに、パラメーター名 値
で引数を渡すことがよくあります。
# X: 引数の順序に依存する ./foo.sh true true 1 # O: パラメーター名で指定する ./foo.sh --foo --bar --param 1
PowerShell でスクリプトを書いた時も、Param()
を使って標準的に行われるパターンです。
# O: パラメーター名で指定する ./foo.ps1 -Foo -Bar -Param 1
Windows バッチでもシェルスクリプトのように、パラメーターで引数を指定したいですね。
foo.bat --foo --bar --param 1
パラメーターで引数を渡すメリットは、引数が順序に縛られずパラメーター名さえわかっていれば任意の順序で指定できることです。スクリプトを利用するときに圧倒的に楽です。
Windows バッチファイルでパラメーターを指定して引数を渡す
次のようなシェルスクリプトがあったとして..。
#!/bin/bash set -euo pipefail while [ $# -gt 0 ]; do case $1 in --foo) _FOO=true; shift 1; ;; --bar) _BAR=true; shift 1; ;; --param) _PARAM=$2; shift 2; ;; --param2) _PARAM2=$2; shift 2; ;; *) shift ;; esac done if [[ "${_FOO:=""}" == "true" ]]; then echo "--foo detected"; fi if [[ "${_BAR=""}" == "true" ]]; then echo "--bar detected"; fi if [[ "${_PARAM:=""}" != "" ]]; then echo "--param ${_PARAM}"; fi if [[ "${_PARAM2:=""}" != "" ]]; then echo "--param2 ${_PARAM2}"; fi
これに相当するWindows バッチファイルでの書き方の例を示します。
@echo off setlocal :parse if "%~1"=="" GOTO endparse if "%~1"=="--foo" (set _FOO=true) if "%~1"=="--bar" (set _BAR=true) if "%~1"=="--param" (set _PARAM=%~2) if "%~1"=="--param2" (set _PARAM2=%~2) shift GOTO parse :endparse if "%_FOO%"=="true" (echo --foo detected) if "%_BAR%"=="true" (echo --bar detected) if not "%_PARAM%"=="" (echo --param %_PARAM%) if not "%_PARAM2%"=="" (echo --param2 %_PARAM2%) endlocal
想定通り、任意のパラメーターを指定できるのがわかります。
> parse.bat > parse.bat --foo --bar --foo detected --bar detected > parse.bat --foo --bar --param 1 --foo detected --bar detected --param 1 > parse.bat --foo --bar --param2 5 --foo detected --bar detected --param2 5 > parse.bat --foo --bar --param2 5 --param 100 --foo detected --bar detected --param 100 --param2 5 > parse.bat --foo --bar --param 1 --param2 5 --foo detected --bar detected --param 1 --param2 5
簡単な説明
:parse
から :endparse
が引数の指定です。
Windows バッチに while
構文がないので、 goto
で代用しています。引数解析は、shift で引数をずらしながら、空になるまでgoto でループするだけです。
setlocal
と endlocal
でスクリプト内の変数を外部出さないようにすると、実行シェルに影響与えないのでお行儀がいいです。
まとめ
Windows バッチファイルも便利。