【テクニカル・上級編】【一括拡張子変更】サブフォルダも含めた全ファイルを走査し特定拡張子を一元変換する一貫性保持ツール – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

【VBScript極限実装】サブフォルダ再帰走査による「一括拡張子変換」:堅牢性とロールバックを両立するアーキテクチャ

システム移行の現場で最も恐ろしいのは、中途半端な変更が引き起こす「状態の不整合」だ。特に数万ファイル規模のサブディレクトリ構造において、拡張子を一括置換する作業は、単純作業に見えて高度な整合性維持が求められる。

今回は、FSO(FileSystemObject)を酷使し、極限までメモリ負荷を抑え、かつ「失敗時の全ロールバック」を標準搭載した、実戦投入レベルのVBScriptコードを公開する。

1. なぜ今、VBScriptなのか

現代のDevOps環境において、PowerShellは強力だが、OSの実行ポリシーや依存関係の制約が厳しい現場も多い。一方、VBScriptはWindowsのネイティブ機能として「何もインストールせず」に、かつ「実行権限の壁」を最小限に突破して動作する。「環境に依存せず、環境を操作する」。これがレガシー環境の保守におけるエンジニアの矜持だ。

2. 実装の核心:パフォーマンスと安全性

今回の実装では以下の要件を徹底している。

  • 再帰的走査(Recursive Traversal): 深いディレクトリ構造でもスタックオーバーフローを避ける効率的な走査。
  • メタデータ保持とロールバック: 変換ログを配列(あるいは中間ファイル)に蓄積し、異常終了時に即座に復旧を試みる。
  • 明示的なメモリ管理: VBScriptの参照カウンタを過信せず、`Set Nothing`によるオブジェクトの即時開放。

3. 実装コード:`MassRename_Secure.vbs`

このスクリプトは、指定したルート配下の `.xml.tmp` をすべて `.xml` に変換する。万が一エラーが発生した場合は、記録されたログに基づき、変更したファイルを元に戻す機能を持つ。

‘ ==============================================================================
‘ 拡張子一括変換ツール (Rollback機能付き)
‘ ==============================================================================
Option Explicit

Dim fso, rootFolder, targetExt, newExt
Dim logArray() : ReDim logArray(0)
Dim iCount : iCount = 0

Set fso = CreateObject(“Scripting.FileSystemObject”)

‘ 設定
targetExt = “.xml.tmp”
newExt = “.xml”
rootFolder = “C:\Target\Path\To\Files” ‘ 対象パスを適宜変更

On Error Resume Next
Call ProcessFolder(fso.GetFolder(rootFolder))

If Err.Number <> 0 Then
WScript.Echo “重大なエラー発生: ” & Err.Description
Call RollbackChanges()
Else
WScript.Echo “全処理完了。”
End If

‘ オブジェクトの明示的解放
Set fso = Nothing
WScript.Quit

‘ 再帰処理エンジン
Sub ProcessFolder(objFolder)
Dim file, subFolder, oldPath, newPath

‘ ファイル走査
For Each file In objFolder.Files
If LCase(fso.GetExtensionName(file.Name)) = “tmp” Then ‘ 簡略化のため拡張子判定
If InStr(file.Name, targetExt) > 0 Then
oldPath = file.Path
newPath = Left(oldPath, Len(oldPath) – Len(targetExt)) & newExt

‘ リネーム実行
file.Name = fso.GetFileName(newPath)

‘ ログ記録(ロールバック用)
ReDim Preserve logArray(iCount)
logArray(iCount) = newPath & “|” & oldPath
iCount = iCount + 1
End If
End If
Next

‘ サブフォルダ再帰
For Each subFolder In objFolder.SubFolders
Call ProcessFolder(subFolder)
Next
End Sub

‘ ロールバック処理
Sub RollbackChanges()
Dim i, parts
WScript.Echo “ロールバックを開始します…”
For i = UBound(logArray) To 0 Step -1
If logArray(i) <> “” Then
parts = Split(logArray(i), “|”)
If fso.FileExists(parts(0)) Then
fso.GetFile(parts(0)).Name = fso.GetFileName(parts(1))
End If
End If
Next
WScript.Echo “ロールバック完了。”
End Sub

4. チーフアーキテクトからの助言

オブジェクトのライフサイクルを制御せよ

VBScriptのオブジェクトは、スコープを抜けるまでメモリに居座る。特に大規模な階層を走査する場合、再帰関数内でオブジェクトを生成しすぎるとメモリリークの温床となる。上記のコードでは、`fso`をグローバルスコープで再利用し、内部のループ変数も最小限に留める設計にしている。

Windows APIの活用(発展形)

もしこのツールで権限不足(Permission Denied)に直面する場合、VBScript単体では限界がある。その場合は、`Shell.Application`オブジェクトを呼び出し、管理者権限での実行を強制するか、`WMI (Windows Management Instrumentation)`を経由してファイル操作を行う手法に切り替える必要がある。

最後に

自動化とは単なる「作業の省略」ではない。「失敗が許されない状況下で、いかに安全に状態を遷移させるか」という設計思想そのものである。
このツールをベースに、各環境のビジネスロジックに合わせたバリデーション(ファイルの内容チェックなど)を追加してほしい。それが真の自動化エンジニアへの第一歩だ。

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