【テクニカル・上級編】【パス解析】GetAbsolutePathNameとGetParentFolderNameを用いたファイルパスの解体・正規化 – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

VBScriptを掌握する極限の知見:FSOパス解析の深層とメモリ最適化の美学

レガシーシステムの深部、あるいはWindows自動化の最前線において、FileSystemObject (FSO) は依然としてインフラストラクチャの神経系として機能している。

世の中には「動けばいい」という妥協に満ちたコードがあふれている。特にファイルパスの操作において、自前で `InStrRev` や `Mid` を組み合わせた脆弱な文字列パースを行っているコードを見ると、アーキテクトとして深い絶望を覚える。Windowsのファイルパス構造は、UNCパス、ドライブレター、相対パスの解決など、開発者が想像する以上に複雑怪奇である。

今回は、FSOが提供するパス解析の要である `GetAbsolutePathName` と `GetParentFolderName` を極限まで使い倒し、さらにVBScriptにおけるメモリ管理の真実を交えながら、堅牢なパス操作の極意を伝授する。

—

1. パス解析の二大巨頭:`GetAbsolutePathName` と `GetParentFolderName` の本質

FSO (`Scripting.FileSystemObject`) のメソッド群は、単なる文字列操作関数ではない。背後でOSのファイルシステムドライバやシェル空間と対話し、正規化された結果を返す強力なエンジンである。

`GetAbsolutePathName` によるパスの正規化と絶対パス化

相対パス(`.` や `..` を含む曖昧なパス)を、OSが解釈可能な完全な絶対パスへ変換する。このメソッドの真価は、「実際にそのファイルが存在するかどうかに関わらず、純粋なパスの構文規則に基づいて解決する」点にある。

Dim fso, rawPath, absolutePath
Set fso = CreateObject(“Scripting.FileSystemObject”)

‘ カレントディレクトリ基準の相対パスを絶対パスへ変換
rawPath = “.\logs\..\data\output.txt”
absolutePath = fso.GetAbsolutePathName(rawPath)

WScript.Echo absolutePath
‘ 出力例: C:\MyProjects\data\output.txt (実行環境のパスに依存)

この挙動は、タスクスケジューラやサービスからVBScriptを実行した際によく起こる「カレントディレクトリの迷子問題」を根絶するための絶対的な防壁となる。

`GetParentFolderName` による階層構造の解体

フルパスから「親フォルダのパス」を抽出する。多くのプログラマブルな言語にある `dirname` に相当するが、FSO版はUNCパス(`\\server\share\folder\file.txt`)に対しても正確に動作する点が優れている。

—

2. 実践:フルパスの完全分解とメタデータ抽出のイディオム

実務において、ひとつのファイルパスから「ドライブ」「親フォルダ」「ファイル名」「拡張子」を完璧に切り離し、構造化データとして扱いたい場面は多々ある。

以下のコードは、FSOの各メソッドを組み合わせ、妥協のないパス分解を行う実用的なプロシージャである。

Option Explicit

Sub ParseFilePath(ByVal targetPath)
Dim fso
Set fso = CreateObject(“Scripting.FileSystemObject”)

On Error Resume Next

‘ 1. 絶対パスへの正規化(相対パスや不整合なスラッシュを補正)
Dim absPath
absPath = fso.GetAbsolutePathName(targetPath)

If Err.Number <> 0 Then
WScript.Echo “致命的なエラー: 無効なパスが指定されました -> ” & targetPath
Exit Sub
End If

‘ 2. 各要素の抽出
Dim driveLetter, parentFolder, fileName, baseName, extension

driveLetter = fso.GetDriveName(absPath) ‘ ドライブ名 (例: C:)
parentFolder = fso.GetParentFolderName(absPath) ‘ 親フォルダパス
fileName = fso.GetFileName(absPath) ‘ ファイル名 + 拡張子
baseName = fso.GetBaseName(absPath) ‘ 拡張子を除いたファイル名
extension = fso.GetExtensionName(absPath) ‘ 拡張子のみ

On Error GoTo 0

‘ 結果の出力(システムログやデバッグ用)
WScript.Echo “— パス解析結果 —”
WScript.Echo “元パス : ” & targetPath
WScript.Echo “絶対パス : ” & absPath
WScript.Echo “ドライブ : ” & driveLetter
WScript.Echo “親フォルダ : ” & parentFolder
WScript.Echo “ファイル名 : ” & fileName
WScript.Echo “ベース名 : ” & baseName
WScript.Echo “拡張子 : ” & extension
WScript.Echo “———————-”

‘ 3. メモリの明示的解放(後述)
Set fso = Nothing
End Sub

‘ 実行テスト
Call ParseFilePath(“..\configs\..\settings.ini”)

—

3. シニアエンジニアが知るべき「メモリ最適化」とオブジェクトのライフサイクル

VBScriptのメモリ管理は、COM (Component Object Model) の参照カウンタ(Reference Counting)に依存している。ここで多くのエンジニアが犯す致命的な誤りが、「スクリプト終了時に自動解放されるから `Set obj = Nothing` は不要」という神話の盲信である。

VBScriptにおけるCOMオブジェクトの寿命とメモリリーク

短命なスクリプトであれば大きな問題にならないが、数百、数千のファイルをループ処理するバッチスクリプトの中で `CreateObject(“Scripting.FileSystemObject”)` を乱用したり、解放処理を怠ったりすると、以下の問題を引き起こす。

1. 参照カウンタの停滞: スクリプトブロックを抜けるまで、またはプロセスが終了するまでCOMコンポーネントがメモリ上に保持され続ける。
2. メモリフラグメンテーション: 大規模なファイル監視・処理システムにおいて、ヒープ領域の断片化を誘発し、最悪の場合はVBScriptホスト (`wscript.exe` / `cscript.exe`) の予期せぬクラッシュ(例外コード 0xC0000005: アクセス違反)につながる。

極限まで最適化されたアーキテクチャの鉄則

大量処理を行うループ内では、オブジェクトの生成と破棄のライフサイクルを厳密に制御せよ。

‘ 【アンチパターン】ループ内でインスタンス生成を繰り返し、解放もしない
‘ For i = 1 To 10000
‘ Dim fso: Set fso = CreateObject(“Scripting.FileSystemObject”)
‘ ‘ 処理…
‘ Next

‘ 【推奨される実装】インスタンスはループ外で1度だけ生成し、処理完了後に即座に破棄する
Dim fso
Set fso = CreateObject(“Scripting.FileSystemObject”)

Dim i, targetPath
For i = 1 To 1000
targetPath = “C:\Logs\app_” & i & “.log”
‘ パス操作やファイル存在確認
If fso.FileExists(targetPath) Then
‘ 処理
End If
Next

‘ アーキテクトの美学:スコープを抜ける前に明示的に解放する
Set fso = Nothing

さらに、大規模な文字列結合やパスの再構築を行う際は、VBScriptのバリアント型(Variant)の暗黙の型変換オーバーヘッドを意識し、不必要なオブジェクト生成を極限まで排除することが、高パフォーマンスなレガシーシステムの維持には不可欠である。

—

総括

VBScriptは過去の遺物と揶揄されることがある。しかし、Windows環境の根底において、その軽量性とOSへの親和性は今なお唯一無二の存在感放っている。

FSOのパス解析メソッドの本質を理解し、メモリのライフサイクルを支配した者だけが、何年経過しようとも安定して稼働し続ける「壊れない自動化スクリプト」を構築できる。コードの1行1行にエンジニアの魂と知見を宿せ。それが、プロフェッショナルとしての仕事である。

タイトルとURLをコピーしました