【実務・中級編】【上級プロフェッショナル向け】フォルダ双方向同期における「タイムスタンプ衝突(両方変更)」を検知して安全退避する自動解決ロジック – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

VBScriptで挑む「双方向同期」の深淵:衝突(Conflict)を制する者が自動化を制す

業務自動化の世界で、最も甘美で、最も危険な罠。それが「フォルダの双方向同期」だ。
多くのエンジニアは、単に「日付が新しい方をコピーする」という単純なロジックで実装を始める。だが、現実はそう甘くない。ネットワーク遅延、OSのタイムスタンプ更新の不整合、そして何より「両方で同時期に編集された」というタイムスタンプ衝突(Race Condition)が、貴方の渾身のツールを「データを破壊するだけの怪物」に変える。

今回は、FSO(FileSystemObject)を駆使し、衝突を検知して安全に「退避(Conflict Rename)」させる、プロダクションレベルの堅牢な同期ロジックを伝授する。

—

1. なぜ「単純比較」では破綻するのか

多くの初心者は、以下のロジックを組む。
「Aの更新日時 > Bの更新日時 なら AをBへコピー」

これは、同期タイミングが完全に隔離されているという幻想に基づいている。しかし、ビジネス現場では「移動中に双方が更新される」ことは日常茶飯事だ。ここで単純比較をすると、「後から同期した側が、相手の変更分を無情に上書きして消し去る」という致命的なデータ消失事故が発生する。

我々プロフェッショナルが目指すべきは、「失わないこと」だ。衝突時は上書きせず、両方のファイルを生かしたまま、別名で退避させる。これが鉄則である。

—

2. 衝突検知の極意:判定ロジックの設計

衝突を検知するための条件は、以下の3つをすべて満たす場合だ。

1. ファイルが存在する:双方に同じ名前のファイルがある。
2. 内容が異なる:ファイルサイズまたはタイムスタンプが異なる(ハッシュ判定が理想だが、VBScriptではFSOのDateLastModifiedが現実解)。
3. 双方向更新の疑い:前回同期時点から、双方のファイル更新日時が「基準時刻」より新しい。

これを実現するために、同期時には必ず「同期完了時刻」を記録するメタデータ(あるいは隠しファイル)を保持すべきだ。今回はシンプルかつ強力な実装として、FSOのタイムスタンプ比較をベースにした退避ロジックを示す。

—

3. 実装:衝突解決エンジン(VBScript)

このコードは、ファイルが衝突した際に `Filename.yyyymmdd_hhmmss.conflict` として退避させる安全設計となっている。

‘ VBScript: Robust Sync Engine Core
Option Explicit

Dim fso: Set fso = CreateObject(“Scripting.FileSystemObject”)

Sub SyncFiles(sourcePath, destPath)
Dim srcFile, dstFile

‘ フォルダ内の全ファイルを走査
For Each srcFile In fso.GetFolder(sourcePath).Files
Dim dstPath: dstPath = fso.BuildPath(destPath, srcFile.Name)

If fso.FileExists(dstPath) Then
Set dstFile = fso.GetFile(dstPath)

‘ タイムスタンプが異なる場合、衝突とみなして退避処理
If srcFile.DateLastModified <> dstFile.DateLastModified Then
HandleConflict srcFile, dstFile
End If
Else
‘ 存在しない場合は単純コピー
srcFile.Copy dstPath, True
End If
Next
End Sub

Sub HandleConflict(src, dst)
‘ 現在時刻を用いた一意な退避ファイル名生成
Dim timestamp: timestamp = Year(Now) & Right(“0” & Month(Now), 2) & Right(“0” & Day(Now), 2) & _
“_” & Right(“0” & Hour(Now), 2) & Right(“0” & Minute(Now), 2)

Dim conflictPath: conflictPath = dst.Path & “.” & timestamp & “.conflict”

‘ 衝突したファイルを退避させる(データの保護)
dst.Copy conflictPath, True

‘ 新しい方を上書きコピー
src.Copy dst.Path, True

‘ ログ出力(業務自動化の鉄則:何が起きたか記録を残す)
LogAction “CONFLICT: ” & dst.Name & ” -> Renamed to ” & fso.GetFileName(conflictPath)
End Sub

Sub LogAction(msg)
Dim logFile: Set logFile = fso.OpenTextFile(“sync_log.txt”, 8, True)
logFile.WriteLine Now & ” | ” & msg
logFile.Close
End Sub

—

4. プロダクション環境への導入アドバイス

このコードを現場で運用する際、以下の3点に注意せよ。

  • 排他制御の考慮: VBScript単体ではネットワーク越し等のファイルロックを完璧に制御できない。処理前に `Err.Clear` を入れたエラーハンドリングを必ず追加し、ファイルが他プロセスで開かれている場合はスキップして次回に持ち越す設計にすること。
  • パスの正規化: `fso.GetAbsolutePathName` を使い、パスのゆらぎ(末尾のバックスラッシュ有無など)を徹底的に排除せよ。ここでのバグはデバッグが困難を極める。
  • 権限の壁: FSOはシステム権限に依存する。実行ユーザーが対象フォルダへのRead/Write/Delete権限を正しく持っているか、事前にチェックするサブルーチンを挟むのがプロの仕事だ。

結びに代えて

自動化とは、単に手作業を置き換えることではない。「想定外の事態が起きたときに、いかに被害を最小化し、情報を保全するか」というリスク管理そのものだ。

「上書き」は思考停止の証。衝突を検知し、ログを吐き、安全を確保する。この設計思想をインストールできたなら、貴方の自動化ツールは、もはや単なるスクリプトではない。堅牢なシステムとして、長く現場を支え続けるはずだ。

さあ、コードを書き換えろ。次なる自動化のステージへ進むために。

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