共有する資料の一覧を前回と今回で比べ、増えたファイルと見当たらないファイルを知りたい。PowerShellのCompare-Objectを使うと、二つの一覧のうち、片方だけに含まれる値を取り出せます。
この例で比べるのは、相対パスの文字列です。同じパスのファイルが書き換わっていても、一覧の文字だけでは内容の更新を検知できません。追加・削除の候補を出す確認と、内容の照合を分けます。
前回を基準に向きをそろえる
ReferenceObjectへ前回、DifferenceObjectへ今回の一覧を渡します。<=は前回だけにある値、=>は今回だけにある値です。矢印の向きを取り違えると、追加と削除の候補が逆になります。
function Compare-FileLists {
param([string[]]$Before = @(), [string[]]$After = @())
$left = @($Before | Where-Object { $null -ne $_ })
$right = @($After | Where-Object { $null -ne $_ })
if ($left.Count -eq 0) {
foreach ($item in $right) {
[pscustomobject]@{InputObject = $item; SideIndicator = '=>'}
}
return
}
if ($right.Count -eq 0) {
foreach ($item in $left) {
[pscustomobject]@{InputObject = $item; SideIndicator = '<='}
}
return
}
Compare-Object -ReferenceObject $left -DifferenceObject $right -CaseSensitive
}
$before = @('docs/a.csv', 'docs/old.csv')
$after = @('docs/a.csv', 'docs/new.csv')
Compare-FileLists -Before $before -After $after
期待する候補はdocs/old.csvが<=、docs/new.csvが=>です。docs/a.csvは両方にあるので表示されません。この結果だけを使ってファイルを消したり移動したりする処理は入れていません。
空の一覧も区別する
片方の一覧が空なら、その側に比較する値がありません。例の関数は空の入力を分岐し、もう一方の項目すべてを対応する向きで返します。両方が空なら結果も空です。
ただし、本当にファイルがゼロだったのか、一覧の取得に失敗したのかは別です。アクセスできなかったフォルダーを空の一覧として保存すると、多数の削除が起きたように見えます。一覧を作る段階のエラー、取得元、取得日時も残してください。
同じ形式のパスで比較する
片方がフルパス、片方が相対パスでは、同じファイルでも別の値になります。区切り文字、基準フォルダー、対象範囲をそろえます。上のdocs/a.csvは説明用の相対パスで、実在する業務ファイルではありません。
例では-CaseSensitiveを付け、大文字小文字が違う名前も区別しています。Windows上の同一性と、ほかの環境へ渡す一覧での同一性は、業務のルールとして決めます。必要なく大文字小文字をそろえると、名前の変化を見逃す場合があります。
重複したパスが一覧にある場合も、入力の作り方を確認します。同じファイルを複数の検索経路から集めたのか、別のルートのファイルを同名として出しているのかを、先に分けてください。
候補の次に実ファイルを見る
前回だけにあるパスは移動や名前変更、取得範囲の違いでも現れます。コードの結果は確認候補として使い、元の保存先と今回の保存先を見比べます。実ファイルの削除があったと、この表だけで断定しないようにします。
同じパスの内容変更も見たい場合は、別にハッシュなどを記録して比べます。この例はWindows PowerShell 5.1とPowerShell 7で架空の一覧を比較する範囲です。ファイル操作は行わず、一覧の向き、空の入力、大文字小文字の条件を確認します。
関連する記事
公式資料
Compare-Object (Microsoft.PowerShell.Utility) – PowerShell | Microsoft Learn
