【楽しようぜ】引数とバッチファイル:一気に「省略」する方法

この記事の概要を簡単まとめ!

  • 久しぶりのバッチファイル作成記事
  • バッチファイルでは任意の引数を扱える
  • バッチファイル実行時に区切り文字を利用すると引数を渡せる
  • 引数は%[n]や%~[n]で中身を扱うことができる
  • 引数が存在する場合の分岐で一気に省略ができる
  • 引数が存在しない場合=デフォルトの場合の処理も必要になる
  • 面倒なことは使えるものを使ってもっと省略してしまえばいい

あの日バッチファイルを書いた記事は、少数ながら毎日誰かが見ている。バッチファイルで使いたい機能の多くはif-elseの条件分岐のようで、それ以外には基本的なことについて知りたい人が多いようだ。ただし私の目標はpowercfgのバッチファイルを解説することであったため、いきなり説明するよりは前段階として使うコマンドの解説を挟んだ上で解説した方が見る人は多い。とはいえ通常検索でいきなり飛んでくる人が多いため、あまり意味がなかったりする。

さて、バッチファイルを作って色々と面倒なクリック動作を省略するくらいには面倒が嫌いな私KIBEKIN。バッチファイルを作っておけば何かを起動するにもcmd.exeを経由すればたった数文字のタイピングで起動できる。しかし、1つのバッチファイル内で複数の選択肢を用意するようにif-else文などで設計した場合、そのバッチファイルを実行後にもう数回タイピング入力が必要になる。作成した当初は問題ないと思うが、慣れてくるとそれすら省略したいように思うことも決してないわけではない。それくらい面倒くさがるなと言われたらそれまでではあるが、省略したいものはしたいものである。

約1年前となる、全3回に分けたバッチファイル作成記事において、引数について解説したのだが、その時の引数はcallコマンドにおける引数について解説した。今回はバッチファイル実行時に、そのバッチファイルで使用するために任意の区切り文字で区別される付属の値=引数を利用して、バッチファイルをもっと省略する方法について書いていく。


ブンブンハローMS-DOSのシェルコマンド、どうもKIBEKINです。

cmdとバッチファイル

おさらい:過去のバッチファイル記事について

約1年ぶりにバッチファイルについて書くことになった私。以前にリンクス岐部を名乗っていた頃に、3回に分けてバッチファイルについて書いた。その記事のリンクが以下である。

バッチファイルの解説は第1回の完全な初心者想定から徐々に難易度をあげていき、第3回のpowercfgで電源プランを簡単に変更するためのバッチファイルを作成するところまでを書き上げたのがこれらである。本命はpowercfgの解説をしたいためで、そのために第1回で基礎を、第2回でif-elseについて解説し、第3回でforとcallを解説した上でのpowercfgとそのオプションについてを解説し、最後に「一般向けの見本」を作成した。この見本は実は私が実際に使用しているのとは、採用している電源プランの関係から違うものになっている。



面倒だが、読むのが面倒という人のために概要を書いておくと、第1回がバッチファイルの基礎として任意のディレクトリにパスを通す(環境変数設定)、任意のアプリケーションを起動する簡単なバッチファイルを作成するところまでを書いている。第2回はプログラミング言語ではお馴染みのif-else文をメインとして関連コマンドとなるgoto文(無能政策ではない), setコマンドとsetlocal, endlocalについて解説し、その後if-elseによって選択肢の中から1つのアプリケーションを選択して起動するバッチファイルを作成するまでを書いている。第3回は集大成であり、forループ(一般的なプログラミングとは仕様が異なる)、callの解説、powercfgとそのオプションの解説を経て、powercfgで電源プランを簡単に変更するバッチファイルを作成するまでを書いている。

いずれの記事においても、実際にそのまま使用できる「使用例」のバッチファイルソースコードを掲載している。これは私が各コマンドの機能を把握し、記述後に実行した際の挙動確認及び想定される誤入力によるエラー確認のために何度も意図的な誤入力を行っている。それによって発見されたバグの修正、意図しない挙動の回避をするための処理や条件分岐を加えた、自作品のバッチファイルである。過去このようなものを私は作っていた。

バッチファイルでは任意の引数を扱える

多くのプログラミング言語において、任意の言語で記述されたテキストファイルの、拡張子をその言語に対応するものに変更したファイルまたは言語のコンパイラによりコンパイルされた実行ファイルをコマンドライン上で実行する時、引数というものを扱うことができる。これは一種のプログラミング言語とも言えるMS-DOS、つまりバッチファイルも同じように引数を扱える。

Windowsでは、引数は一般的に任意の実行ファイル(.exe)を実行する際、オプション1)Windowsの例では、cmdで多用することの多いipconfig.exeで全てのデバイスの接続情報を表示する時にはipconfig /allと入力する。このときの/allがオプションである。ちなみに/allでも-allでもオプションとして認識される。とは別に指定するものである。これについては、Windowsを普通に使っている人はそもそもcmdに触れることはないため分からないことであろうし、cmdを使うとしてもGUIではできない、自分で高度な設定変更を行いたいような人でなければこの仕組みを理解することは難しい。

バッチファイルに関しては原則オプションは存在しないが、引数はバッチファイル側で特別な設定をしなくても扱える。もちろん、引数を使用しないバッチファイルを作ることもできる。多くの場合、バッチファイルを作成するにしても、引数まで意識したバッチファイルを作成することはあまりないであろう。引数を使ってまでバッチファイルで何かするということは、バッチファイルに入れ込む人くらいしかできないであろう。

バッチファイルは実行時に区切り文字を利用すると引数を渡せる

さて、バッチファイルで引数を扱うにはどうしたらいいかという話であるが、cmdからバッチファイルを起動する場合、任意のバッチファイル名の後に区切り文字を使用し、その後は任意の文字列を入力してやればいい。特殊文字や区切り文字そのものを使いたい場合はダブルクォーテーション(“[文字列]”)で囲っておけば問題ない。

ここで区切り文字とは、その名の通り区切り文字である。この区切り文字は多数存在し、バッチファイルで扱える区切り文字は半角スペース( )、セミコロン(;)、カンマ(,)、等号(=)の4つである。しかもバッチファイルでは、区切り文字は混在していても全て区切り文字として機能する。したがって、引数を渡す時は区切り文字については特に意識しなくても問題ないことになる。逆に区切り文字を単純な文字列として使用するには、ダブルクォーテーションを使用することを意識しておかなければ想定しないエラーを誘発することになってしまう。この点は英文字を引数で扱う場合に少々面倒な話になってくる2)参照:コマンドプロンプト | バッチファイル実行時に引数を渡す

引数は通常、9個まで扱える。10個以上は特別な設定を行うことによって使用できるが、これをするのは大規模なソフトウェアで設定を一括で終わらせるためか、或いはクラック目的くらいである。普通にバッチファイルを作成し使用する場合、9個以内で足りることが殆どである。したがって、特別な設定をすることはないので問題ない。よってここからは実際に引数を使った、ソフトウェア起動を超簡略化をしたバッチファイルを作っていく。これもKIBEKINにより動作検証済みの自作品のバッチファイルである。

ソースコードの前に:解説次項

ソースコードに行く前に、解説次項がある。この解説次項はこの記事をいきなり初めて見る人向けに書いたものであり、バッチファイルの基本的なことを知っているとか、仕組みについて知っているとかであれば省略しても構わない。ただ、よく検索からいきなり飛んでくることも考慮して、一応の解説は行っているのである。



まずはcmdの基本コマンド(過去未解説の今回使用分)解説を行う。既に過去3回の記事で基本的なcmdの基本コマンドについては解説済みである。ここでは過去未解説のもので今回使用するものについて解説する。

pause >nul

バッチファイルは通常、ユーザが何か入力するタイミングか明示的に停止するコマンドを入力しない限り、実行すると記述されているコマンドを全て実行しようとする。そのためどこかでエラーが発生したり間違いがあったとしても殆どが一瞬でバッチファイルが終了してしまう。cmdから呼び出さない場合(ダブルクリックなどで直接起動する)、cmd画面が表示されるも一瞬で閉じてしまうため、どうなっているかを確認することはできない。cmdから起動しても、echoが多く出力される結果が長いものとなれば、cmdのバッファを小さく設定していると読み切れないうちに結果がどこかに消えてしまうことが多い。これは単純にバッファを大きくしておけばいいだけのことではあるのだが、いちいちスクロールして読み戻すのは面倒である。

そこで使用されるのがpauseコマンドである。pauseは一般生活で使われる意味で殆ど間違いなく、バッチファイルの実行を「一時停止」する場合に使用する。例としては以下のように使用する。

pause_example
pause_example実行例。pauseを実行すると、「続行するには何かキーを押してください…」と表示され、押さない限りはバッチファイルの実行が一時停止される。

これを実際に実行すると画像の通りになる。pauseは実行すると「続行するには何かキーを押してください…」という表示がなされ、これが表示されている間はバッチファイルは”pause”、つまり一時停止しているわけである。そして何かしらのキーを押せば、pauseは解除されてpauseの次の文からバッチファイルが実行を再開する。この時に反応するキーは文字キー、テンキー、矢印キー、ファンクション、escなどであり、ctrl, alt, shift, fn, 半角/全角などは押しても解除されないようになっている。もっとも、pauseを解除する際は押しやすいスペースやエンターキーを使うことであろう。しかし反応するキーは広いので、それまでの結果を見たい場合うっかり押してしまわないように注意すること。また、マウスのクリックではpauseは解除されないため、マウスを使えばpause以前の結果を見ることができる。

pauseテクニック1:ctrl+Cで中止できる

バッチファイルをpauseにより一時停止中で、もしそのバッチファイルをそれ以上実行させずに中止したい場合、ctrl+Cで中止するかどうかを尋ねる文面が出現する。イメージ画像が以下である。

pause_ctrl+C
pauseが実行されているタイミングでctrl+C(中止コマンド)を入力したときの状態。すぐには中止せず、y/n(大文字・小文字区別なし)を入力して続行か中止を選択する。

この時、(Y/N)でYes(中止)かNo(続行)かを、yまたはnを入力してエンターキーを押すことで選択する。大文字・小文字の区別はされず、またyかn以外の入力は受け付けないシステムになっている。空白エンターキーしても同じことを問い続ける。エンターキー押しっぱなしにすると永遠と「バッチ ジョブを終了しますか (Y/N)?」と表示されるのは、ある意味のホラーである。

これの使いどころとしては、バッチファイルを作成し実行した際、特定のタイミングでブレークポイントをセットする場合や、テスト時にエラーが発生しそうな場所に明示的にブレークポイントを入れて確認するなどの使い方ができる。バッチファイルの場合は一般のテキストエディタで編集可能な分、IDEのようなブレークポイントを1クリックでセットできるようなものではないので、このようにすることも必要である。そもそもIDEでバッチファイルを扱えたかが不明であるが。




pauseテクニック2:pause実行時に出るメッセージを消す

pauseには、オプションは存在しない。そのため、pauseはpauseとして使用するしかないのである。ただ、pause実行時は必ず「続行するには何かキーを押してください…」とメッセージが出てしまう。これを非表示にしたいことや、英文に変えたいということはあるはずだ。

その際のテクニックとして、結果のファイル出力を利用する。このとき、ファイルではなくNull空間に出力することで、不要なファイル生成を行わずにこの表示を消すことができる。

このようにすることで、pauseすると必ず表示される文面は表示されなくなる。このようにしても何かキーを押せばpauseは解除される。ただ、この状態では何も表示されないでpauseが実行されるので、デフォルト文面を削除する代わりにechoで入力を促したり他の文面を表示して、ユーザにpauseしていることを明示する必要がある。例えば、上記の例のようにecho Push any keys...と書けば、それっぽくなるのでいいだろう3)参照:pause(バッチファイルの処理を一時停止する)日本語表示はどうしてもダサく感じる。

変数の特殊な取り扱い:文字列で指定部分から取り出す

バッチファイルの変数は、型の定義を必要としない。そのため、setコマンドと任意の変数名を利用すれば、代入したい値が文字列でも数値でも、(特殊文字を除いて)特に意識することなく何でも代入することができる。また、オプションの/Aで数式を扱え、/Pでユーザに任意の文字列または数値を入力させそれを変数に代入することができる。

また、変数は展開を行うとき、通常は変数を%で囲み%[変数名]%の形で展開する。この方法は変数に代入されている値をそのまま表示するものであるが、あるときには変数の特定の部分の文字列についてのみ展開したい場合があるであろう。一般的なプログラミング言語においてsubstr()という関数を使用するが、バッチファイルでも同じものが存在する。ただしバッチファイルの場合、その方法が一般的なプログラミング言語とは異なるものである。その方法については下記の表にまとめている4)参照:Windowsバッチ(.bat)で文字列の切り出しを行う(Substrみたいな) | ぱーくん plus idea

変数展開時の書式(変数名var) どのように変数が展開されるか
%var% varの中身を全て展開する
%var:~m% m文字目から変数末尾まで
%var:~m,n% m文字目からn文字分
%var:~m,-n% m文字目から、変数末尾からn文字分抜いたもの
%var:~-m% 変数末尾起点にm文字目から変数末尾まで
%var:~-m,n% 変数末尾起点にm文字目からn文字分
%var:~-m,-n% 変数末尾起点にm文字目から変数末尾からn文字分抜いたもの

これがバッチファイルにおけるsubstr()である。しかし表の羅列だけでは、果たしてどのような結果になるのかが分かりにくいであろう。そのため、実際にバッチファイルを作成し実行した。そのソースコードと実行結果を以下に掲載する。

var_expand_test
変数展開テストを行ったもの。分かりやすくするため、16進数の0~Fをvarに入れて、m=7, n=3で展開した。

実行結果と表の書式による展開のされ方を見ていけば、具体性があり非常にわかりやすいものとなるはずだ。ちなみに、%var:~-m,-n%はn>mとなるとき、結果は何も出力されない。これは文字列が全部削られてしまうことで、何もないことに同じとなるからである。つまり空の変数を展開しているのと同じだ。この現象が起きるため、テストではm>nとしている。

展開時の書式については、1つの変数を展開するときに複数の書式を同時に利用することはできないが、1つ1つ区切って展開するのであれば同じ変数を何度でも使いまわすことができる。極端な話、任意の文字列(1文字ではない)が代入された変数をわざわざ1つずつ展開するということも可能である。その場合、forループ(ただし変数の遅延展開が必要、詳細はぐぐれ)を使った方が便利である。流石にC言語のようにはできるわけではないが。

今回解説が必要な事項については以上である。これと、過去3回で解説していることを使用して、引数を利用した一気に省略するバッチファイルを次項で作成していく。



実践バッチファイル:任意のOfficeを引数を利用して起動する

ここでようやく、今回の集大成となるバッチファイルのソースコード、そして実行例を示すことができる。ところで、あのMicrosoft定番のオフィススイートであるOfficeシリーズは一般的にWord, Excel, PowerPointの3つがあればどうにかなるものである。この3つのうち1つを引数で起動するものを作成する。また同一のバッチファイルにおいて、引数の入力が一致しない場合と引数がない場合はユーザに入力させるモードに移行するように設定している。

test005_office
test005_office.batの実行結果。ここでは一般家庭でも使用するWord, Excel, PowerPointに限定している。引数なしでも正常に起動して選択させるようにして、引数ありの場合はその文字が合致するかを検証し、合致しない場合は引数なしと同様に選択させるようにして、エラーが発生しないようにしている。

上記がソースコード、そしてこれを実行した結果である。ここで、起動するOfficeは事実上最後の買い切り型Officeとなる2019である。これが非常に面倒な365や2019より古いOfficeになるとディレクトリ名が異なるため、これは自分が使用するOfficeに合わせて変更すること。

このバッチファイルの流れを簡略にリスト化すると以下の通りである。

  1. バッチファイル実行時、引数が存在するかを確認。存在する場合、その引数の文字列を検証する。存在しない場合、デフォルトモードとしてユーザに選択させるモードを開始。
    1. 1.1. 引数の文字列がWord, Excel, PowerPointのいずれかの頭文字、または完全名であれば該当するものを起動。それ以外の場合、「該当するものがない」としてデフォルト=選択させるモードに飛ばす。
  2. ユーザに選択させるモードの時、どれかを起動するか終了する以外はループしてもう一度リストから選択させる。
  3. いずれかのOfficeアプリケーション起動した、またはquit(終了)した場合、バッチファイルを終了する。

要するにこのような処理が行われていると考えれば良い。本当のところはcallなども含めてもう少し詳しい処理が存在するが、ここでは大体の流れがつかめていれば問題ない。これは業務で使用するとか、そう言うことではないからである。




テクニック:完全名でも対応させるには変数展開で解説したあれを使う

このバッチファイルでは、引数は各Officeアプリケーションの頭文字だけでなく、完全名でも対応している。完全名とは、各アプリケーションの正式名称である。つまり、Word, Excel, PowerPointをそれぞれ引数としても起動できるようにしたということだ。しかし、これでわざわざ別の処理を記述してまで起動するのは、バッチファイルの内容の簡略化を考えると利巧とは言えない。そこで起動方法を使いまわすのである。

各アプリケーションを起動するのはサブルーチンとして69行目から記述してある。ここを見ると、各アプリケーションの頭文字で起動していることが分かるはずだ。そこで、完全名で引数に文字列が代入された場合、それの頭文字だけ取得する処理を行い、これでアプリケーションの起動を使いまわすという方法を取る。ここでこれ以前に解説したものが生きてくる。

54~56行目では、52行目で引数を変数argSubstCheckに代入し、完全名で入力されたそれを頭文字を入れるため用の変数argSubstCheckOneに、変数展開の書式で「0文字目から1文字分」展開してそれを代入させている。一般にコンピュータは最初を「1」ではなく「0」と扱うことが多いため、0文字目から1文字分とすれば頭文字だけ取得できる、ということである。

ちなみに大文字であっても小文字であっても、判定には全く影響しない。これはif /iのオプションを使用しているためで、これを利用することで大文字と小文字を区別しなくなるためである。これはユーザがどのように入力するかを選べないからこそ使用するモードである。

解説は以上である。

面倒なことは使えるものを使ってもっと省略してしまえばいい

今回は完全な趣味とも言える領域の、バッチファイルで引数を使いもっと省略する方法と、その例のバッチファイルのソースコード及び結果を掲載した。ここまで来てしまうと流石に面倒が嫌いにしても程があると言われそうだが、面倒なことは面倒であることには変わりはない。

実は本命である引数利用でOfficeを起動するバッチファイルを作成したのは、以前からバッチファイルでOfficeを起動していたからである。しかし以前のバージョンはいちいち実行しては指定する手間があったので、慣れてくるとこれが面倒な操作に思えてきたのである。そしてこのブログにおいて、バッチファイル関係は多数の閲覧者が存在し、その中でバッチファイルでまだしっかり取り扱ったことがないのが引数利用であった。久しぶりにバッチファイルを書こうと思ったときには、ネタとして即決だった。実際組んでみると、私自身も勉強になったものである。

MS-DOS, バッチファイルとは奥が深いもので、これだけやっていてもまだ書けることはあると思われる。これについては私がバッチファイルで変なことかシステムに変更を加えるようなことをしない限りは書けることはなさそうだが、もし書けるようになったら不定期に書くことにしている。次回以降も楽しみに待っているといい。

 

以上、引数とバッチファイル:一気に「省略」する方法、であった。それでは、次回の記事で会おう。ン、バァーイ!

 

KIBEKIN at 12:26 May 7th, 2021


スポンサーリンク




脚注

脚注
本文へ1 Windowsの例では、cmdで多用することの多いipconfig.exeで全てのデバイスの接続情報を表示する時にはipconfig /allと入力する。このときの/allがオプションである。ちなみに/allでも-allでもオプションとして認識される。
本文へ2 参照:コマンドプロンプト | バッチファイル実行時に引数を渡す
本文へ3 参照:pause(バッチファイルの処理を一時停止する)
本文へ4 参照:Windowsバッチ(.bat)で文字列の切り出しを行う(Substrみたいな) | ぱーくん plus idea
KIBEKIN
会社員という働き方が合わないのに会社員になってしまってから、半ば自分からリタイア後ブログクリエイターとなり活動してきた社会不適合者。今後の活躍の約束とHIKAKINリスペクトの意味を込め、リンクス岐部からKIBEKINに改名した。

コメントを残す

メールアドレスが公開されることはありません。
名前は必須項目となります。記入をお願いいたします。

CAPTCHA


日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)