【テクニカル・上級編】【スケルトン構造複製】実ファイルはコピーせずフォルダの階層構造(ディレクトリツリー)のみを一括再現するツール – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

【スケルトン構造複製】実ファイルを含めないフォルダ階層一括ミラーリング術

レガシーシステムの保全、あるいは巨大なデータレイクの移行前段階において、ディレクトリ構造のみを安全かつ高速にクローンしたいという要求は、インフラエンジニアであれば幾度となく直面する課題だ。

PowerShell全盛の現在においても、依然としてスタンドアロンで動作し、追加ランタイムのインストールすら許されない閉域網のWindows環境において、VBScript (Visual Basic Scripting Edition) は究極の即効性を持つインフラ自動化の切り札として君臨し続けている。

今回は、ファイルシステムオブジェクト(FSO)のライフサイクルを極限までチューニングし、巨大な実ファイルを一切触れることなく、フォルダの階層構造(スケルトン構造)だけを美しく再構築するプロダクション品質のスクリプトを公開する。

—

1. FSOアーキテクチャの核心:なぜ「スケルトン複製」なのか

数テラバイトに及ぶNASの移行や、アーカイブ前のディレクトリ構造監査において、単なるファイルコピー(`Xcopy` や `Robocopy`)では無駄なI/Oが発生し、ネットワーク帯域やストレージの寿命を無駄に消費する。

FSO(`Scripting.FileSystemObject`)を用いた再帰的走査により、「ファイル実体へのアクセスを完全にバイパス」し、メモリ上でディレクトリツリーの論理構造のみを構築・転写するアプローチをとることで、以下の圧倒的なメリットが生まれる。

  • ゼロ・フットプリントI/O: 実データの読み書きが一切発生しないため、処理速度が物理ストレージの速度ではなく、OSのメタデータ処理能力の限界値に張り付く。
  • 権限・例外の局所化: 個別のファイルに対するアクセス権エラー(Access Denied)に阻まれることなく、フォルダ階層のみを確実に抽出できる。
  • メモリリークの完全根絶: オブジェクトの参照カウンタとスコープのライフサイクルを厳密に管理し、長時間の連続稼働でもプロセス肥大化を起こさない。

—

2. 【実装】Skeleton Mirroring Engine

以下のコードは、エラーハンドリング、パスの正規化、そしてFSOのインスタンス管理を極めたプロダクションコードである。そのまま `.vbs` ファイルとして保存し、バッチ処理やタスクスケジューラから即座に実行可能だ。

‘ ==============================================================================
‘ Script Name : SkeletonDirectoryMirror.vbs
‘ Description : 実ファイルを除外し、フォルダ階層(スケルトン)のみをミラーリングする
‘ Author : Chief Architect
‘ ==============================================================================
Option Explicit

Const OverwriteExisting = True
Dim objArgs, strSourcePath, strDestPath
Dim fso, dblStartTime

‘ 実行時間の計測開始
dblStartTime = Timer

‘ 1. 引数の検証
Set objArgs = WScript.Arguments
If objArgs.Count < 2 Then WScript.Echo "[ERROR] 引数が不足しています。" & vbCrLf & _ "Usage: cscript.exe SkeletonDirectoryMirror.vbs ”
WScript.Quit 1
End If

strSourcePath = objArgs(0)
strDestPath = objArgs(1)

‘ 2. FSOの初期化
Set fso = CreateObject(“Scripting.FileSystemObject”)

‘ ソースパスの存在確認
If Not fso.FolderExists(strSourcePath) Then
WScript.Echo “[ERROR] コピー元フォルダが存在しません: ” & strSourcePath
Set fso = Nothing
WScript.Quit 2
End If

WScript.Echo “=== スケルトン複製処理を開始します ===”
WScript.Echo “Source : ” & strSourcePath
WScript.Echo “Destination : ” & strDestPath
WScript.Echo “————————————————–”

‘ 3. 再帰処理の実行
Call CopyFolderSkeleton(fso, strSourcePath, strDestPath)

‘ 4. 終了処理
Set fso = Nothing

WScript.Echo “————————————————–”
WScript.Echo “[SUCCESS] 処理が完了しました。 実行時間: ” & FormatNumber(Timer – dblStartTime, 2) & ” 秒”
WScript.Quit 0

‘ ==============================================================================
‘ Subroutine : CopyFolderSkeleton
‘ Arguments : fso (FileSystemObject), srcPath (String), dstPath (String)
‘ Description: 再帰的にサブフォルダを走査し、実体を作らずに階層を複製する
‘ ==============================================================================
Sub CopyFolderSkeleton(ByRef fso, ByVal srcPath, ByVal dstPath)
Dim objSourceFolder, objSubFolder
Dim targetSubDir

On Error Resume Next

‘ ソースフォルダの取得
Set objSourceFolder = fso.GetFolder(srcPath)
If Err.Number <> 0 Then
WScript.Echo “[WARNING] フォルダへのアクセス権がありません、または存在しません: ” & srcPath
Err.Clear
Exit Sub
End If

‘ コピー先フォルダの作成(存在しない場合のみ)
If Not fso.FolderExists(dstPath) Then
fso.CreateFolder(dstPath)
If Err.Number <> 0 Then
WScript.Echo “[ERROR] フォルダの作成に失敗しました: ” & dstPath & ” (” & Err.Description & “)”
Err.Clear
Exit Sub
End If
WScript.Echo “[CREATE] ” & dstPath
End If

‘ サブフォルダコレクションの走査(ファイルは完全に無視する)
For Each objSubFolder In objSourceFolder.SubFolders
targetSubDir = fso.BuildPath(dstPath, objSubFolder.Name)
‘ 再帰呼び出し
CopyFolderSkeleton fso, objSubFolder.Path, targetSubDir
Next

‘ メモリ上の参照解放(COMオブジェクトのライフサイクル管理)
Set objSubFolder = Nothing
Set objSourceFolder = Nothing

On Error GoTo 0
End Sub

—

3. チーフアーキテクトが解説するコードの急所

A. ファイルコレクションへのアクセスを完全に断つ

このコードの最も美しい点は、`Folder.Files` コレクションを一切イテレートしていない点にある。VBScriptのコレクション走査は、内部的にCOMのIEnumVARIANTインターフェースを叩くため、数百万ファイルのメタデータをメモリにロードしようとすると、確実にパフォーマンス低下やメモリ枯渇を招く。`SubFolders` のみに限定することで、極限まで無駄を削ぎ落としている。

B. COMオブジェクトのスコープとガベージコレクション

VBScript(基盤となるWSH/VBAのCOMランタイム)は、.NETのような高度な世代別GCを持たない。参照カウント方式(Reference Counting)でメモリ管理が行われるため、再帰呼び出しの内部で作成された `objSubFolder` や `objSourceFolder` は、ループの脱出時やサブルーチンの終端で明示的に `Nothing` を代入して参照を切る必要がある。これを怠ると、深い階層を走査した際にメモリリークが発生し、プロセスが肥大化する。

C. レジリエンス(耐障害性)の確保

`On Error Resume Next` による局所的なエラーハンドリングは、大規模移行における鉄則だ。「アクセス拒否(Access Denied)」や「パスが長すぎる(MAX_PATH問題)」といったレガシー環境特有の例外踏み抜きに対し、スクリプト全体が異常終了(クラッシュ)するのを防ぎ、スキップして処理を継続する設計にしている。

—

4. 現場で使える運用ティップス

1. 文字コードと実行エンジンの選択:
UTF-8で保存したスクリプトをWindows標準の `cscript.exe` で実行する場合、日本語パスが含まれる環境では文字化けのリスクがある。実行時は必ずコマンドプロンプトから以下のように明示的に呼び出すこと。

cscript //nologo SkeletonDirectoryMirror.vbs “C:\SourceDir” “D:\DestSkeleton”

2. MAX_PATH(265文字制限)の回避:
WindowsのレガシーAPI制限により、パスが260文字を超えるとFSOはエラーを返す。もし対象ツリーが深い階層を持つ場合は、宛先パスをショートパス(8.3形式)に変換するか、Windows 10/11環境であればあらかじめレジストリで `LongPathsEnabled` を有効化しておくこと。

—

総括

VBScriptは「古い言語」ではない。「OSの深層に最もダイレクトに、余計な依存関係なしでアクセスできる軽量なシステムインターフェース」である。

今回紹介したスケルトン構造複製スクリプトは、インフラの保守現場において、巨大なデータ構造のハンドリングを極限まで効率化する。オブジェクトのライフサイクルとメモリの挙動を完全に掌握したコードだけが、現場のトラブルを未然に防ぐことができるのだ。

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