†DOSとバッチとスクリプト†

ワイルドカード「?」が正常に機能しない

作成開始日 2018.09.27
最終更新日 2018.09.27

本来、ワイルドカード「?」は任意の1文字に置換されるはずだが、実際にはまともに機能しない。例えば、半角英数字10文字からなるhtmファイル(例:j815626345.htm)を抽出する場合;

  dir ??????????.htm
  for %%f in (??????????.htm)

などとすれば良い筈だが、実際にはこれでは期待した結果は得られない。

●問題点1:指定文字数以下のファイルがすべて含まれてしまう

例えば、5文字のファイル名を持つBATファイルを抽出するために「dir ?????.bat」とすると、5文字以下のすべてのファイルが含まれてしまう。「test1.bat」のような5文字ファイル名だけではなく、「test.bat」や「vz.bat」や「c.bat」なども全て該当してしまう。仕様なのかも知れないが、使う側から見ればバグとしか考えられない。では、上記のように10文字指定すると、10文字以下のファイル名がすべて抽出されるのかと言うと−−実は更に酷い状況になる。

●問題点2:「?」は7個までしか意味をなさない

つまり、上記のように「?」を10個並べると、個数が無視されて「*」と同じなってしまう。10文字以下どころか、11文字でも20文字でも50文字でも全て該当してしまう。恐らく、これは8.3時代の名残で、最長ファイル名が8文字である以上、「?」を8個(以上)並べたものは「*」と同等に扱われるのだろう。

●問題点3:日本語ファイル名は「?」5個で全該当

上記は半角英数字のファイル名の場合だが、日本語ファイル名に関しては「?」5個で「*」に該当してしまう。これもDOS時代の名残のなのか、それともUTF-8で新たに発生した問題だか不明だが、日本語ファイル名が混じっている状態では、「?」は4個までしか使えない。

●対処方法

まあ、これらは長年放置されてきたバグで、一ユーザーにはどうしようもない。DOSでは「?」は使わない、というのが最善の自衛策。とは言え、じゃあ、どうすんの?というハナシになるのだが−−例えば、バッチに文字列の長さを取得する関数があれば良いのだが、そんな便利なものがあるはずもなく、各ユーザーさんが文字数カウントのルーチンを自作している状況。もう、バッチは止そうぜ、perlにしよう!かとも思ったが、まあ、今回は次のような方法で対処。

setlocal enabledelayedexpansion

for %%f in (*.htm) do (
  set st0=%%f
  set st1=!st0:~0,10!.htm
  if "!st0!"=="!st1!" (echo %%f)
)
基本的な考え方は、頭から10文字切り取って、元のファイル名と同じならば長さは10文字、という単純なもの。10文字以上のファイル名ならば当然同じにはならないし、10文字未満の場合も「頭から10文字」の中に拡張子部分が食い込んでくるので、同一にならない(例:test1234.htm→test1234.h.htm)。ただし、拡張子がないファイルを抽出する場合は、指定文字数未満でも一致してしまうので要注意(ダミーの拡張子を付けるという対処法はあるが)。


【DOSとバッチとスクリプト目次】 【ホーム】