制御不能な「ファイルの山」に終止符を。VBScriptによる究極の世代管理ロジックをマスターする
「バックアップを取るスクリプトは作った。でも、フォルダの中を見ると、数年前の古いバックアップファイルが溜まり続けていて、ディスク容量を圧迫している……」
現場で自動化を進めていると、必ずと言っていいほど直面する問題です。マクロの記録や、断片的なコードのコピー&ペーストでは、こうした「運用上のリスク」を解決することはできません。
こんにちは。今日は、単なる「ファイル操作」の一歩先、「システムのライフサイクルを管理する」ための技術、すなわち「世代管理(ローテーション)」についてお話ししましょう。
「最新の5世代だけを残し、それより古いものは自動的に計算して消去する」。このロジックを完璧に実装できるようになれば、あなたのVBScriptは「便利な道具」から「信頼できるシステム」へと昇華します。
ここをクリアすれば、VBScriptの基本はバッチリですよ。さあ、始めていきましょう。
1. 思考の設計図:世代管理をどう分解するか?
プログラミングにおいて、いきなりコードを書き始めるのは二流のやり方です。まずは、頭の中で「アルゴリズム(手順)」を組み立てましょう。
今回のミッションは「最新N世代のみ保存」です。これを実現するための思考プロセスは以下の4ステップです。
1. スキャン: 指定したフォルダ内のファイルをすべて洗い出す。
2. 情報の抽出とソート: ファイル名ではなく「更新日時」に注目し、新しい順に並べ替える。
3. 境界線の決定: 「最新N件」がどこまでかを特定し、それより後ろにあるファイル(古いファイル)を特定する。
4. 安全な実行: 特定した古いファイルを、エラーを回避しながら削除する。
ここで重要なのは、「ファイル名でソートしてはいけない」ということです。バックアップファイル名に日付が入っていれば名前順でも可能ですが、運用が変わった瞬間に崩壊します。「ファイルのプロパティ(更新日時)」を基準にすること。これがプロの設計です。
2. 武器の準備:FileSystemObject (FSO) と ArrayList
VBScriptでファイル操作を行う際の絶対的な相棒が `FileSystemObject` です。しかし、FSO単体では「ファイルを日付順に並べ替える」という機能を持っていません。
そこで、私は実務において「System.Collections.ArrayList」という、.NET Frameworkの機能をCOM経由で呼び出すテクニックをよく使います。これを使うことで、VBScript単体では面倒な「ソート(並べ替え)」を、たった数行で、かつ高速に実行できるのです。
3. 実践:世代管理スクリプトの完全版
それでは、現場でそのまま使えるレベルのコードを提示します。コードの中には、なぜその処理が必要なのか、魂を込めてコメントを刻みました。
'===============================================================================
' 【実務向け】ファイル世代管理スクリプト(最新N世代保持)
'
' 概要: 指定フォルダ内のファイルを更新日時順にソートし、
' 指定した世代数を超えた古いファイルを自動削除する。
'===============================================================================
Option Explicit
' --- 設定エリア ---
Dim targetFolder, keepCount
targetFolder = "C:\Backup\Logs" ' 対象となるフォルダパス
keepCount = 5 ' 残したい最新の世代数
' --- メイン処理 ---
Main targetFolder, keepCount
Sub Main(path, n)
Dim fso, folder, file, fileList
' 1. オブジェクトの生成
Set fso = CreateObject("Scripting.FileSystemObject")
' 2. フォルダの存在確認(ここがプロの守り)
If Not fso.FolderExists(path) Then
WScript.Echo "Error: 指定されたフォルダが存在しません: " & path
Exit Sub
End If
Set folder = fso.GetFolder(path)
' 3. ArrayListの生成(ソート用)
' VBScript単体では困難な「並べ替え」を、.NETの力を借りてスマートに解決
Set fileList = CreateObject("System.Collections.ArrayList")
' 4. ファイル情報の収集
' ファイルオブジェクトそのものではなく、"更新日時|フルパス" という文字列でリスト化する
' これにより、ソート後にパスを簡単に取り出せるようにする
For Each file In folder.Files
' 更新日時を降順(新しい順)に並べるため、先頭に日付を入れるテクニック
' ※日付を文字列として比較可能にするため、YYYYMMDDHHMMSS形式に変換するのが理想的だが
' ここではシンプルに、ソート後に利用しやすいよう「更新日時」をキーにする
' ここでは ArrayList の Sort メソッドを最大限活かすため、一旦オブジェクトを格納
fileList.Add file
Next
' ファイルが指定数以下なら、何もせず終了
If fileList.Count <= n Then
WScript.Echo "管理対象のファイル数が規定数以下です。処理を終了します。"
Exit Sub
End If
' 5. ソート処理(更新日時を基準に降順ソート)
' ArrayListのSortはデフォルトで昇順。
' ここでは、カスタム比較を行う代わりに、一度「日付_パス」の形式でリストを作り直す手法をとる
' ※今回は分かりやすさを優先し、ファイルオブジェクトを直接扱えるよう、
' 一旦「日付文字列」と「パス」を組み合わせたリストを作成してソートします。
Dim sortList, item, f
Set sortList = CreateObject("System.Collections.ArrayList")
For Each f In folder.Files
' キー:更新日時(YYYYMMDDHHMMSS) + パス
' これにより、文字列ソートだけで「新しい順」が実現できる
sortList.Add FormatDateTimeForSort(f.DateLastModified) & "|" & f.Path
Next
' 昇順にソート(古いものが上、新しいものが下になる)
sortList.Sort
' 6. 古いファイルの削除
' 「全件数 - 残したい件数」が、削除すべきファイルの数になる
Dim deleteCount, i, targetPath
deleteCount = sortList.Count - n
WScript.Echo "世代管理を開始します... (対象: " & sortList.Count & "件, 保持: " & n & "件)"
For i = 0 To deleteCount - 1
' リストの先頭から(=一番古いものから)取り出す
item = sortList(i)
targetPath = Split(item, "|")(1) ' "|" で分割してパス部分を取得
On Error Resume Next ' ファイルが使用中などのエラー対策
fso.DeleteFile targetPath, True
If Err.Number <> 0 Then
WScript.Echo "Warning: 削除失敗 (" & targetPath & ") - " & Err.Description
Err.Clear
Else
WScript.Echo "Deleted: " & targetPath
End If
On Error GoTo 0
Next
WScript.Echo "世代管理が完了しました。"
' 7. 後片付け(オブジェクトのライフサイクル管理)
Set fileList = Nothing
Set sortList = Nothing
Set fso = Nothing
End Sub
' --- 補助関数:ソート用の日付文字列変換 ---
' 日付を「YYYYMMDDHHMMSS」形式の文字列に変換する
' これにより、文字列としてのソートが「時間の前後」と一致するようになる
Function FormatDateTimeForSort(dt)
Dim y, m, d, hh, mm, ss
y = Year(dt)
m = Right("0" & Month(dt), 2)
d = Right("0" & Day(dt), 2)
hh = Right("0" & Hour(dt), 2)
mm = Right("0" & Minute(dt), 2)
ss = Right("0" & Second(dt), 2)
FormatDateTimeForSort = y & m & d & hh & mm & ss
End Function
4. 伝説のアーキテクトが教える「陥りやすい罠」
このスクリプトを運用するにあたって、あなたが絶対に避けるべき「3つの罠」を伝授しておきます。
① 「ファイル使用中」のトラップ
バックアッププロセスがまだ動いている最中に、このスクリプトが走るとどうなるでしょうか? `fso.DeleteFile` は、ファイルが他のプロセスによってロックされているとエラーを吐きます。
上記のコードでは `On Error Resume Next` を使い、エラーが発生しても止まらずに「警告」として記録して次に進むように設計しています。これが「止まらないシステム」を作る知恵です。
② 「パスの区切り文字」の罠
Windowsのパスには `\` が使われますが、文字列操作(`Split` など)を多用する場合、意図しない分割が起きることがあります。今回は `|`(パイプ)という、ファイル名にはまず使われない記号を区切り文字に採用しました。こうした「データの境界線を明確にする工夫」が、堅牢なコードを生みます。
③ オブジェクトのライフサイクル
VBScriptはメモリ管理が自動ですが、大規模な処理を行う場合、使い終わったオブジェクトを `Set obj = Nothing` で明示的に解放する習慣をつけましょう。これは、リソースの枯渇を防ぐ、エンジニアとしての「礼儀」です。
まとめ:ここからがあなたの本番です
今回のスクリプトは、単にファイルを消すだけのものです。しかし、その裏側には「データの特性を理解し、適切なアルゴリズムを選択し、例外的な事態(エラー)を想定する」という、高度なエンジニアリングの思考が詰まっています。
「マクロの記録」は、あらかじめ決まった動きをなぞるだけです。
しかし、今回学んだ「ロジック」は、状況に応じて自ら判断し、動くものです。
ここをクリアすれば、VBScriptの基本はバッチリですよ。次は、このロジックを応用して「古いログをZIP圧縮してから消す」といった、さらに高度な自動化に挑戦してみてください。
応援しています。次回の講義でお会いしましょう!
