0
0

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 1 year has passed since last update.

【shift利用なし】DOS(BATファイル)の引数をすべて取得(10個以上対応)【ワイルドカード】

Last updated at Posted at 2022-09-09

DOSの引数って面倒くさい

この記事を書いている中で、PHPやComposerをうまいこと複数バージョン対応にしたくて 「そうだ、PATHが通っているところにショートカットっぽく実行ファイルを置けばいいんだ」と気付き、試してみた。

例えば、以下の環境・要件のとき

  • 環境
    1. php でPHP8.0のパスが通っていて php7 でPHP7.4を実行したい
    2. php8.1は D:\xampp\php\php.exe に存在する(PATHが通っている)
    3. php7.4は D:\xampp\php7\php.exe に存在する(PATHは通っていない)
    4. php -v はPHP8.1が表示されるようになっている
  • 要件
    1. php7 -v はPHP7.4が表示されるようにする(引数が1つ)
    2. php7 コマンドの引数の数は予測できないがすべて利用できるようにしなければならない
      • php7 引数1 引数2 ... 引数X が使えるようにする
      • 引数は10個以上の可能性もある

まずは1を解決(引数が1個)

これは簡単、 D:\xampp\php\php7.bat を配置し、php7.4を実行してやれば良い

\xampp\php\php7.bat
@echo off
echo execute: D:\xampp\php7\php.exe %1
D:\xampp\php7\php.exe %1

2行目は実運用では不要だが、何を実行したかわかるようにechoしている。
以下、実行結果

> php7 -v
execute: D:\xampp\php7\php.exe -v
PHP 7.4.22 (cli) (built: Jul 28 2021 09:44:30) ( ZTS Visual C++ 2017 x64 )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies

間違いなくphp7.4が実行されている。

DOSの引数は10個までしか扱えない?

たとえば、以下のコマンドを実行する場合

> php7 a b c d e f g h i j k l

こうすれば行けそうな気がするが

\xampp\php\php7.bat
@echo off
echo execute: D:\xampp\php81\php.exe %1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12
D:\xampp\php7\php.exe %1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12

こう実行されてしまう

> php7 a b c d e f g h i j k l
execute: D:\xampp\php7\php.exe a b c d e f g h i a0 a1 a2

a0 a1 a2 ってなんだ?と思うが、これは、%n のn部分に2文字が利用できないため。
つまり '%10' は 引数%1 + 数字の0 という扱いになってしまう。
しかも引数が少ないと

> php7 a b c
execute: D:\xampp\php7\php.exe a b c       a0 a1 a2

こうなってしまうため、要件2の 引数の数は予測できない にマッチしない。
(10個以内ならマッチするが、無駄な半角スペースが入る)
そこで、下記記事のようにshiftを使うことで回避ができる。

つまり、こうすれば良い(前者の記事から引用して改変している)

\xampp\php\php7.bat
@echo off
 
set count=1
set argv=

:loop
if "%1"=="" goto :confirm
set argv=%argv% %1%
set /a count+=1
shift
goto loop
 
:confirm
echo execute: D:\xampp\php81\php.exe%argv%
D:\xampp\php7\php.exe%argv%

これで php7 -S localhost:8000php7 artisan breeze:install react のようなケースにも対応できる。

注意
laravelはcomposer側に工夫が必要なので、引数が使えるというだけで、このままで正常動作するわけではない

引数にワイルドカードが使えるじゃん!

ここまででひとまず完成ではあるが、同じことをcomposerで設定しようとしたところ、composer.batに以下のような記述があった。

composer.bat
@echo OFF
:: in case DelayedExpansion is on and a path contains ! 
setlocal DISABLEDELAYEDEXPANSION
php "%~dp0composer.phar" %*

なんと、%* が使えるではないか

「DOS 引数」でググっても基本的には上記記事のようなshiftで対応するものばかりなで、ソースが見つけられなかった。
唯一見つけた以下の記事を参照すると

バッチ パラメータ %* は、バッチ ファイルに渡される %0 を除くすべての引数を参照するワイルドカードです。

と記載されている(%0については後述)。
この記事が2008年なので、WindowsXP ~ 7の間くらいで採用されたか、NT系の標準仕様なのかもしれない。
早速、試してみよう

\xampp\php\php7.bat
@echo off 
echo execute: D:\xampp\php81\php.exe %*
D:\xampp\php7\php.exe %*
> php7 a b c d e f g h j k l             
execute: D:\xampp\php7\php.exe a b c d e f g h j k l

なんとたったの3行で実行できた。
試しにちゃんと実行できる引数で試してみる。

> php7 -v
execute: D:\xampp\php7\php.exe -v
PHP 7.4.22 (cli) (built: Jul 28 2021 09:44:30) ( ZTS Visual C++ 2017 x64 )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies

> php7 -S localhost:8000
execute: D:\xampp\php7\php.exe -S localhost:8000
[Fri Sep  9 11:25:56 2022] PHP 7.4.22 Development Server (http://localhost:8000) started

完璧!
composerさん、大切な気付きをくれてありがとう。
shiftを駆使している皆さん、早く気づいて!

番外:引数9個しか使えてなくない?(%0について)

説明を省いたが %0 が存在し、コマンド(batファイル)の(フル)パスが引数となる。
本件の場合は D:\xampp\php\php7.bat になる。
使わないので省略しているがこれで引数の合計が10個となる。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?