【実務・中級編】【完全一致重複ファイル抽出】CertUtil ハッシュ値と Dictionary を組み合わせたディスク内の重複ファイル一括検出・整理 – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

VBScriptで極めるファイル管理:CertUtilとDictionaryによる高速重複排除エンジン

現場のエンジニア諸君。VBScriptは「レガシーな遺物」ではない。Windows環境において、外部ライブラリのインストールを許されない閉鎖的なサーバー環境でも、OS標準の機能だけで強力な自動化を実現できる「最後の砦」だ。

今日は、ディスク容量を圧迫する重複ファイルを一網打尽にするツールを設計する。単にファイルを列挙するだけのコードは素人だ。我々が目指すのは、I/Oのボトルネックを最小化し、メモリリークを回避し、大規模環境でも破綻しない堅牢なアーキテクチャである。

1. なぜ「CertUtil」と「Dictionary」なのか

重複ファイルの検出において、ファイルサイズ比較はあくまで一次フィルタに過ぎない。バイナリレベルの完全一致を保証するには、ハッシュ値(SHA256)の生成が不可欠だ。

  • CertUtilの選択: `Get-FileHash`(PowerShell)の方がモダンだが、呼び出しオーバーヘッドがある。一方、`CertUtil`はWindows標準かつ高速で、パイプラインを通したストリーム処理にも耐えうる。
  • Dictionaryの選択: 検索計算量O(1)を実現する唯一の解だ。ハッシュ値をキー、ファイルパスを値として保持することで、数万ファイルの探索も一瞬で終わらせる。

2. プロダクションコード:重複ファイル抽出エンジン

このスクリプトは、単なるコピペコードではない。エディタに貼り付ければ、そのまま業務品質のツールとして機能する。

Option Explicit

‘ — 設定エリア —
Const TARGET_DIR = “C:\TargetFolder”
Const REPORT_FILE = “C:\Report\DuplicateFiles.log”
‘ ——————

Dim fso, dict, shell, ts
Set fso = CreateObject(“Scripting.FileSystemObject”)
Set dict = CreateObject(“Scripting.Dictionary”)
Set shell = CreateObject(“WScript.Shell”)
Set ts = fso.CreateTextFile(REPORT_FILE, True)

WScript.Echo “スキャン開始: ” & TARGET_DIR
ScanFolder fso.GetFolder(TARGET_DIR)
WScript.Echo “スキャン完了。”
ts.Close

Sub ScanFolder(folder)
Dim file, hash, cmd, result

‘ ファイル走査
For Each file In folder.Files
‘ CertUtilでハッシュ値を計算
cmd = “certutil -hashfile “”” & file.Path & “”” SHA256″
result = shell.Exec(cmd).StdOut.ReadAll

‘ 出力結果の2行目(ハッシュ値部分)を抽出
hash = Trim(Split(result, vbCrLf)(1))

If dict.Exists(hash) Then
‘ 重複を発見:ログに記録
ts.WriteLine “DUPLICATE: ” & file.Path & ” (Original: ” & dict(hash) & “)”
Else
‘ 初出の場合は辞書に登録
dict.Add hash, file.Path
End If
Next

‘ サブフォルダを再帰的に走査(必要に応じて有効化)
‘ For Each subFolder In folder.SubFolders
‘ ScanFolder subFolder
‘ Next
End Sub

3. 設計上の鉄則:パフォーマンスと安定性のために

このコードを「実務」で使う上で、以下の3点を意識しなければならない。

① I/Oの負荷を制御せよ

`shell.Exec`は別プロセスを起動する。数万ファイルを処理する場合、プロセスの起動・終了がOSの負荷となる。もしスキャン対象が膨大であれば、`WScript.Sleep 10` をループ内に挟み、OSのCPUスケジューラに呼吸させる配慮が必要だ。

② メモリ管理の意識

VBScriptの`Scripting.Dictionary`は非常に優秀だが、巨大なハッシュテーブルを構築し続けるとメモリを圧迫する。対象が数十万ファイルを超える場合は、途中でDictionaryをクリアするか、SQLiteなどの軽量データベースへ逃がす設計変更を検討すべきだ。

③ セキュリティとパスの正規化

`CertUtil`の出力は環境によって改行コードが異なる場合がある。`Trim(Split(result, vbCrLf)(1))` は最も安定した抽出手法だが、万が一の異常系(ファイルアクセス権限エラー等)に備え、`On Error Resume Next` を活用したエラーハンドリングを必ず追加すること。

4. 最後に:エンジニアとしての矜持

このスクリプトは、ファイルサーバーの肥大化に悩む情シス部門や、大量のログデータを扱う開発者にとっての強力な武器になる。

自動化の本質は「コードを書くこと」ではない。「何がボトルネックかを理解し、OSの挙動を味方につけ、手作業を根絶すること」だ。

今回のコードをベースに、さらに「重複ファイルの自動削除(Move命令への変更)」や「レポートのHTML出力」へカスタマイズを試みてほしい。VBScriptの真価は、こうした地味だが確実な自動化の積み重ねにある。

現場からは以上だ。健闘を祈る。

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