VBScriptの限界を突破せよ:FSOとRegExpを融合させる「ワイルドカード」検索の極意
VBScriptを駆使する現場のエンジニア諸君。君たちは今なお、`FileSystemObject (FSO)`の力不足に頭を抱えていないか?
「特定の拡張子を持つファイルを一括処理したい」。そんな時、多くの初心者は `FSO.GetFolder(path).Files` をループで回し、`If InStr(…)` や `If Right(…)` を乱発する。だが、それはあまりに稚拙な設計だ。拡張子が複雑に絡み合うログファイルの抽出や、中間文字を含む曖昧なファイル検索において、その場しのぎの条件分岐は必ずバグの温床となる。
VBScriptには、標準でワイルドカードを解釈するAPIは存在しない。しかし、VBScriptの真髄である「COMオブジェクトの組み合わせ」を知る者にとって、それは障害ではない。今回は、FSOの走査能力と、正規表現(RegExp)の解析能力を融合させた、プロダクションレベルの「ワイルドカード検索エンジン」の設計思想を伝授する。
—
1. なぜ「If文の羅列」ではいけないのか
保守性が低いコードの典型は、検索条件が増えるたびに `If` 分岐を増やしていくことだ。「`data_.log` も含めたい」「`error_??_2023.txt` も対象にしたい」。こうなった瞬間、君のコードはスパゲッティ化し、テスト工数は指数関数的に増大する。
プロの設計:
ファイル名という「文字列」の判定を、ロジックから切り離してエンジン化せよ。正規表現こそが、この要件における唯一無二の最適解だ。
—
2. 実装:RegExpを活用した堅牢なファイル検索エンジン
以下に、再利用性と堅牢性を担保した、本番環境でそのまま使えるコードを示す。このコードは、ワイルドカード(“ や `?`)を正規表現に変換してマッチングを行うアーキテクチャを採用している。
‘ — 指定したディレクトリからワイルドカードパターンでファイルを取得する —
Function GetFilesByPattern(targetFolder, pattern)
Dim fso, folder, file, regex, matches
Set fso = CreateObject(“Scripting.FileSystemObject”)
Set regex = CreateObject(“VBScript.RegExp”)
‘ 1. ワイルドカードを正規表現に変換
‘ \. -> \\. (エスケープ)
‘ -> . (任意の文字列)
‘ ? -> . (任意の1文字)
regex.Pattern = “^” & Replace(Replace(Replace(pattern, “.”, “\.”), “”, “.”), “?”, “.”) & “$”
regex.IgnoreCase = True ‘ Windowsファイルシステムに合わせて大文字小文字を区別しない
Set GetFilesByPattern = CreateObject(“Scripting.Dictionary”)
‘ 2. フォルダが存在するかチェック(堅牢性のためのガード節)
If Not fso.FolderExists(targetFolder) Then Exit Function
Set folder = fso.GetFolder(targetFolder)
‘ 3. ファイル走査
For Each file In folder.Files
If regex.Test(file.Name) Then
‘ Dictionaryにフルパスを格納(重複を許さない設計)
GetFilesByPattern.Add file.Path, file.Path
End If
Next
End Function
‘ — 利用例 —
Dim files, path
Set files = GetFilesByPattern(“C:\Logs”, “app_???_.log”)
For Each path In files.Keys
WScript.Echo “対象ファイル: ” & path
Next
—
3. チーフアーキテクトからの助言:現場で生き残るための注意点
① `Dictionary` オブジェクトの活用
戻り値として `Array` ではなく `Dictionary` を使用していることに注目してほしい。ファイルパスは一意(Unique)であるべきだ。検索結果を後続の処理(データベース挿入やログ集計)に渡す際、Dictionaryであれば重複チェックやキーによる即時アクセスが可能になり、パフォーマンスが劇的に向上する。
② 大規模ディレクトリへの配慮
数万件のファイルが存在するディレクトリで `folder.Files` を全走査するのは、I/O負荷が高い。もし対象が膨大な場合は、`Shell.Application` オブジェクトを用いた「名前空間検索」への切り替えを検討せよ。ただし、それは今回のような単純なタスクにはオーバーエンジニアリングだ。まずはこのコードで運用し、ボトルネックを確認してから最適化するのが「正しい手順」である。
③ エラーハンドリングの徹底
本コードでは省略しているが、プロダクションコードでは `On Error Resume Next` を活用し、アクセス権限がないファイルに対する `Permission Denied` を適切にハンドリングせよ。ツールが突然落ちるのは、エンジニアの恥だ。
—
結論:道具を使いこなすということ
VBScriptは古い言語かもしれない。だが、適切な設計思想を持って扱えば、これほど軽量かつ強力な自動化の武器は他にない。
「FSOでできないから」と諦めていた君へ。
「言語仕様に足りないものは、オブジェクトの組み合わせで補う」。この思考こそが、業務自動化エンジニアとしての君の価値を決定づけるのだ。
さあ、このコードをコピーして、君の現場の「非効率な手作業」を一つずつ消し去ってほしい。健闘を祈る。
