【入門編】【初心者向け】GetFolder.SubFoldersを活用した指定した深さ(階層レベル)限定のフォルダ列挙スクリプト – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク
スポンサーリンク

階層の迷宮を支配せよ:FSOで実現する「指定した深さ」だけのフォルダ列挙術

「マクロの記録」から一歩踏み出し、自分でコードを書き始めた皆さん、ようこそ。
自動化の世界へ足を踏み入れた今、皆さんは「ファイルやフォルダを自在に操りたい」という渇望を感じているはずです。

そのための最強の武器が、FileSystemObject(FSO)です。

しかし、フォルダ操作の学習を進めていくと、必ずと言っていいほど一つの「壁」にぶつかります。それは、「サブフォルダの中のサブフォルダ……と、どこまでも深く潜ってしまう問題」です。

多くの教材では「再帰処理(自分自身を呼び出す関数)」を使って全階層を探索する方法を教えます。しかし、実務においては「直下のフォルダだけ知りたい」「2階層目まででいい」という場面が多々あります。むしろ、無制限の探索は処理の肥大化やエラーの元です。

今日は、再帰処理という「魔法」を使わずに、「指定した深さ(階層)だけを的確に、かつ安全にスキャンする」という、極めて実用的でプロフェッショナルな手法を伝授しましょう。

ここをクリアすれば、VBScriptの基礎はバッチリですよ。

1. 基礎知識:FileSystemObject (FSO) とは?

まず、武器の確認です。VBScriptでファイルやフォルダを扱うには、`Scripting.FileSystemObject` というオブジェクトを生成する必要があります。

  • Folderオブジェクト: 特定のフォルダを表す。
  • SubFoldersコレクション: そのフォルダの直下にある「サブフォルダ」の集まり。

例えば、`GetFolder(“C:\Temp”).SubFolders` と書けば、Tempフォルダのすぐ下にあるフォルダたちにアクセスできます。しかし、これだけでは「その下の階層」には手が届きません。

2. なぜ「再帰処理」を避けるのか?

「再帰処理」は、コードが短く美しく見えるため、初学者が最初に学ぶ手法です。しかし、伝説的なエンジニアの視点から見ると、以下のリスクが見えます。

1. スタックオーバーフローのリスク: 階層が異常に深い構造(ネットワークドライブなど)で実行すると、メモリを使い果たしてプログラムがクラッシュします。
2. 制御不能な探索: 「どこまで探すか」の制限をかけるロジックが、再帰の中に混ざるとコードが複雑化し、デバッグが困難になります。
3. パフォーマンスの重み: 無駄に深い階層まで探索することは、I/O負荷(ディスクへのアクセス)を増大させ、システムのパフォーマンスを削ります。

今回のテーマである「指定した深さで止める」手法は、これらをすべて回避できる、非常に堅牢なアプローチなのです。

3. 実装の極意:キュー(Queue)を用いた階層管理

再帰を使わずに階層を管理する最もスマートな方法は、「次に探索すべきフォルダと、その現在の深さをセットで記録しておく」という考え方です。

イメージとしては、探索待ちのリスト(キュー)を作り、そこに「フォルダ情報」と「今何階層目か」をメモしながら進んでいく感じです。

【実践コード】指定階層限定のフォルダ列挙スクリプト

以下のコードは、指定したルートフォルダから、指定した深さ(Level)までを探索し、結果を表示するものです。

' ==========================================================================
' Script Name: DepthLimitedFolderEnumerator.vbs
' Description: 指定した階層レベルまでのフォルダを列挙する
' Author: Legendary Architect
' ==========================================================================

Option Explicit

' --- 設定エリア ---
Dim targetPath, maxDepth
targetPath = "C:\Your\Target\Path" ' ← ここを調査したいパスに変更してください
maxDepth   = 2                       ' ← 何階層目まで探索するか(0=ルートのみ, 1=直下まで...)

' --- メイン処理 ---
Main targetPath, maxDepth

Sub Main(rootPath, limit)
    Dim fso, rootFolder, taskQueue, currentTask
    
    Set fso = CreateObject("Scripting.FileSystemObject")
    
    ' パスの存在チェック(これ、基本中の基本です!)
    If Not fso.FolderExists(rootPath) Then
        MsgBox "エラー: 指定されたパスが見つかりません。" & vbCrLf & rootPath, vbCritical
        Exit Sub
    End If

    Set rootFolder = fso.GetFolder(rootPath)
    
    ' 探索待ちリスト(Dictionaryを使用して、フォルダと階層をペアで管理)
    ' Key: Folderオブジェクト, Value: 現在の階層数
    Set taskQueue = CreateObject("Scripting.Dictionary")
    
    ' 最初のフォルダ(ルート)を登録
    taskQueue.Add rootFolder, 0
    
    WScript.Echo "--- 探索開始: " & rootPath & " (最大階層: " & limit & ") ---"

    ' 探索待ちリストが空になるまでループ(これが再帰を使わないコツ!)
    Do While taskQueue.Count > 0
        ' リストの先頭から一つ取り出す
        ' ※Dictionaryは順序が保証されないため、本来はCollection等を使うのが理想ですが、
        '   今回はシンプルにするため、Keyを一つずつ取り出して処理する手法をとります。
        Dim key
        key = taskQueue.Keys()(0)
        currentTask = taskQueue(key)
        
        ' リストから取り出し済みの要素を削除
        taskQueue.Remove key
        
        ' 現在のフォルダを表示
        WScript.Echo String(currentTask * 2, " ") & "|-- " & key.Name & " (Level: " & currentTask & ")"
        
        ' もし現在の階層が制限(maxDepth)未満なら、その下のサブフォルダをリストに追加
        If currentTask < limit Then
            Dim subFolder
            For Each subFolder In key.SubFolders
                ' 次に探索すべきフォルダと、その階層(current + 1)を登録
                ' すでに登録されている場合のエラー回避のため、存在チェックを入れるのがプロの技
                If Not taskQueue.Exists(subFolder) Then
                    taskQueue.Add subFolder, currentTask + 1
                End If
            Next
        End If
    Loop

    WScript.Echo "--- 探索終了 ---"
    
    ' オブジェクトの解放(メモリ管理を意識しましょう)
    Set taskQueue = Nothing
    Set fso = Nothing
End Sub

4. コードの徹底解剖:何が起きているのか?

このスクリプトの心臓部は、`Do While taskQueue.Count > 0` のループ部分にあります。

① 探索待ちリスト(Dictionary)の役割

ここでは、`Dictionary` オブジェクトを「作業机」として使っています。

  • `taskQueue.Add subFolder, currentTask + 1`

この一行が魔法の言葉です。「このフォルダは、次の階層(+1)として調べてね」という指示をメモして机に置いておくのです。

② 階層のコントロール

`If currentTask < limit Then` という条件文に注目してください。 これが「防波堤」の役割を果たします。指定した深さに達したフォルダについては、その下の `SubFolders` を見に行く(リストに登録する)処理をスキップします。これにより、無限の深さへの侵入を物理的に阻止しています。

③ インデントによる可視化

`String(currentTask * 2, ” “)` というテクニックを使っています。階層が深くなるほど空白が増えるため、実行結果がツリー構造のように見え、人間が直感的に理解できるようになっています。

5. 陥りやすいエラーと回避策

プロフェッショナルへの道は、エラーを予見することから始まります。

1. 「アクセスが拒否されました」エラー
システムフォルダ(`C:\Windows` など)をスキャンしようとすると、権限のないフォルダに触れた瞬間にスクリプトが停止します。

  • 対策: `On Error Resume Next` を使う方法もありますが、何が起きたか分からなくなるため、実務では「エラーが発生したフォルダはスキップして次に進む」というエラーハンドリングを丁寧に記述するのが定石です。

2. パスの末尾の扱い
`C:\Temp` と `C:\Temp\` は、FSOでは同じように扱えますが、文字列操作でパスを結合する際は、バックスラッシュ(`\`)が重複したり抜けたりしないよう、常に注意を払ってください。

最後に

いかがでしたか?
「再帰を使わずに、リスト(キュー)を使って階層を管理する」という手法は、一見すると少し複雑に見えるかもしれません。しかし、一度このロジックをマスターしてしまえば、あなたは「制御不能なプログラム」から「制御可能な、信頼性の高い自動化ツール」へと進化を遂げたことになります。

プログラミングは、単に動くものを作ることではありません。「意図した通りに、安全に、効率よく動くものを作る」ことこそが本質なのです。

ここをクリアすれば、VBScriptの基本はバッチリですよ。自信を持って、次の自動化プロジェクトに挑んでください!

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