Windows でバッチファイルと格闘

cuzic です。

今日はいろいろと事情があって、かなぁり久しぶりにバッチファイル(.bat のファイル)を作っていました。

私は MS-DOS => Windows3.1 => Windows95 と、正当な進化の歴史を歩んできた人間なので、もちろん昔はバッチファイルを使っていました。
(とはいえ、Windows 3.1 の頃はほとんど MS-DOS ばかり使っていたが)

EDLINvim の ex モードのようなラインエディタ)でバッチファイルなどを作っていたら、そのうち EDIT (私にとってはSEDIT だったが)のようなスクリーンエディタが登場してとても使いやすくなって感動したものです。

おっさん向けの昔話は置いておくとして、その頃は ERRORLEVEL も駆使したバッチファイルを製作していたのです。しかし、今となってみると、まったく思い出せないので、完全に1から学習するハメになっちゃいました(トホホ)。

すると、あまりにも忘れている上に、奇妙な挙動にすごくびっくりしました。

備忘録的に、バッチを書く上で大事なことを書いておきます。

  • 空白や "" のクオートはシェルではなく、実行するコマンドが解釈する
  • エスケープは ^

例:

 C:\Documents and Settings\cuzic> echo ^(^-^)
 (-)
  • ファイルを渡すときは、DOS形式のファイル名が空白が便利
○ C:\Documents and Settings\cuzic> type "C:\Documents and Settings\cuzic\ntuser.ini"
× C:\Documents and Settings\cuzic> type C:\Documents^ and^ Settings\cuzic\ntuser.ini
   空白は、type コマンドによりファイルの区切りとして解釈されます
○ C:\Documents and Settings\cuzic> type C:\Docume~1\cuzic\ntuser.ini
   DOS形式のファイル名は有効
  • 連続して、コマンドを実行するときは、& でつなげるとできる
      • && だと、前のコマンドが正常実行の場合のみ、|| だと失敗の場合のみに実行できます
  • リダイレクトの位置はいろいろ変えられるみたい
○ C:\Documents and Settings\cuzic> echo hoge > tmp
   C:\Documents and Settings\cuzic> type tmp
   hoge

○ C:\Documents and Settings\cuzic> > tmp echo hoge
   C:\Documents and Settings\cuzic> type tmp
   hoge

○ C:\Documents and Settings\cuzic> echo > tmp hoge
   C:\Documents and Settings\cuzic> type tmp
   hoge
      • 一番先頭で書くのが、列をそろえられてお洒落らしい
  • 上記から、 & を含む文字列を環境変数に格納させて、表示するのは難しい
× set satc=Sex & The City
  ( set satc=Sex ) & The City と解釈され、The コマンドが見つからないため
× set satc=Sex ^& The City
   echo %satc%
  ( echo Sex ) & The City と解釈されます
× set satc=Sex ^^& The City
  ( set satc=Sex ^ ) & The City と解釈されます
○ set satc=Sex ^^^& The City
   echo %satc%
  echo Sex ^& The City と解釈されます

(補足)
ダブルクオートがついたままになるが、

 set satc="Sex & The City"
 echo %satc%
 "Sex & The City"

とすることもできます。
どうもダブルクオートで囲まれると & の解釈は抑止されるようです。

  • start コマンドの挙動はいろいろと謎。
    • 32bit GUI アプリの場合(ほとんどのイマドキの実行ファイル)は処理終了を待たずにプロンプトに戻るが、そうでなければ(DOS コマンドの場合など)終了を待ちます
    • 空白を ^ でエスケープしても、空白を含むファイルは渡せません
    • 第1引数が "" でクオートされていると、コマンドを意図していたとしても、ウインドウタイトルとして解釈されます。
× start "C:\Program Files\Microsoft Office\OFFICE11\EXCEL.EXE"
○ start "" "C:\Program Files\Microsoft Office\OFFICE11\EXCEL.EXE"

バッチの構文解析については ここにまとまっていますが、なんともカオスすぎて意味わかりません。