【実務・中級編】【ファイル同期】2つのフォルダ内の最新更新日時を比較し、最新差分のみを自動集約する同期スクリプト – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

VBScriptで「同期」を語るということ:FSOを使い倒すための極限の作法

ファイルシステムオブジェクト(FSO)は、VBScriptにおける「諸刃の剣」だ。正しく扱えば強力な自動化の武器となるが、ライフサイクル管理を疎かにすれば、メモリリークやハンドルロックを誘発する爆弾と化す。

今回は、2つのフォルダ間で更新日時を比較し、最新版のみを抽出する「差分同期スクリプト」の設計思想を伝授する。単に動くコードを書くのはプログラミングではない。「二度と手を入れる必要がない堅牢な仕組み」を構築することこそ、我々自動化エンジニアの責務だ。

—

1. 差分同期における「思考の罠」と設計方針

多くの初心者は、単純に「フォルダ内のファイルをループして、`DateLastModified` を比較してコピー」というロジックに飛びつく。だが、それでは現場の運用には耐えられない。

  • 排他制御の欠如: コピー中に他のプロセスがファイルを書き換えたらどうなるか?
  • パスの正規化: 末尾のセパレータ(`\`)の有無で、スクリプトは容易に迷子になる。
  • エラーハンドリング: ファイルがロックされている場合、スクリプトが停止してはならない。

今回実装するロジックは、「ソース(コピー元)とターゲット(コピー先)を対等に比較し、常に最新を勝ち残らせる」というアプローチをとる。

—

2. 堅牢な差分同期プロダクションコード

以下のコードは、保守性を考慮し、関数を適切に分離している。そのままコピー&ペーストして環境に合わせてパスを書き換えてほしい。

‘ — 設定エリア —
Const SRC_PATH = “C:\Data\Source”
Const DST_PATH = “D:\Data\Destination”

SyncFolders SRC_PATH, DST_PATH

Sub SyncFolders(sourcePath, destPath)
Dim fso, fldrSrc, fldrDst
Set fso = CreateObject(“Scripting.FileSystemObject”)

‘ パスが存在しない場合のガード節
If Not fso.FolderExists(sourcePath) Or Not fso.FolderExists(destPath) Then
WScript.Echo “エラー: 指定されたフォルダが存在しません。”
Exit Sub
End If

Set fldrSrc = fso.GetFolder(sourcePath)

‘ 同期ロジックの核
Dim file
For Each file In fldrSrc.Files
SyncSingleFile file, destPath, fso
Next

‘ メモリ解放の徹底(VBScriptの基本中の基本)
Set fldrSrc = Nothing
Set fso = Nothing
End Sub

Sub SyncSingleFile(file, destPath, fso)
Dim destFilePath
destFilePath = fso.BuildPath(destPath, file.Name)

‘ ターゲットにファイルが存在しない場合はコピー
If Not fso.FileExists(destFilePath) Then
file.Copy destFilePath, True
WScript.Echo “新規作成: ” & file.Name
Else
‘ 既に存在する場合は更新日時を比較
Dim destFile
Set destFile = fso.GetFile(destFilePath)

‘ ソースが新しい場合のみ上書き
If file.DateLastModified > destFile.DateLastModified Then
file.Copy destFilePath, True
WScript.Echo “更新適用: ” & file.Name
End If
Set destFile = Nothing
End If
End Sub

—

3. なぜこの設計なのか?(アーキテクトの視点)

① `fso.BuildPath` の活用

パスを結合する際、手動で `& “\” &` と書くのは素人のやり方だ。OSのセパレータ環境差異を吸収し、冗長なスラッシュを自動で排除してくれる `BuildPath` を使うのが、プロの最低限の作法である。

② 明示的なメモリ解放

VBScriptはガベージコレクションが強力ではない。特にループ処理内でオブジェクトを生成し続けると、メモリを食いつぶす。`Set obj = Nothing` を省略するエンジニアを、私は「未熟」と判断する。

③ エラーハンドリングの拡張性

今回はシンプルにしているが、本番環境では `On Error Resume Next` を活用し、`Err.Number` をチェックして「ファイルが使用中です」という例外をログに吐き出すロジックを追加すべきだ。

—

4. 実務上の注意点:データベース連携と同期の限界

このスクリプトはファイルシステム上の同期には最適だが、「データベースのレコード同期」をこれで行おうとは考えるな。ファイルにはタイムスタンプがあるが、データベース内のデータ更新には「論理的な順序」が必要であり、ファイル単位の同期ロジックではデータ整合性が崩れるリスクがある。

また、ネットワークドライブ経由での同期を行う際は、必ず `WScript.Sleep 100` などを挟むか、同期の実行タイミングをタスクスケジューラで制御し、重複実行を避ける設計にすること。

最後に:自動化の真髄

「コードを書いて終わり」ではない。自動化エンジニアの真の仕事は、「スクリプトが失敗したときに、いかに迅速に異常を検知し、安全に復旧できるか」という運用設計までをセットで提供することだ。

このスクリプトをベースに、君自身の環境に応じた「堅牢な防壁」を組み込んでほしい。それができた時、君はVBScriptの制約を超えた、真の自動化エンジニアになれるはずだ。

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