📁

インフラ運用の現場で役立つ!Pythonで2つのCSVから「変更点」を自動抽出する方法

に公開

1.はじめに

サーバー内のファイル調査や棚卸しで、定期的にファイル一覧をCSV化している方は多いと思います。
前回の記事では「ファイル一覧を再帰的に取得してCSVに出力するスクリプト」を作成しました。

しかし、運用を続けていると必ずこう思うはずです。
「1ヶ月前と比較して、結局どのファイルが増えて、どれが更新されたの?」

今回は、「新旧2つのCSV」を突き合わせ、差分レポートを自動生成するツールを作ります。

2.作成したコード

import pandas as pd
import sys
import os

def main():
    #引数のチェック
    if len(sys.argv) < 3:
        print("Usage: python csv_diff.py [旧ファイルパス] [新ファイルパス]")
        return

    old_path = sys.argv[1]
    new_path = sys.argv[2]

    #CSVの読み込み
    try:
        df_old = pd.read_csv(old_path, encoding="utf-8-sig")
        df_new = pd.read_csv(new_path, encoding="utf-8-sig")
    except Exception as e:
        print(f"Error: ファイルの読み込みに失敗しました。 {e}")
        return

    #比較のキーとなる列を指定
    cols = ["第1階層", "第2階層", "第3階層(以降のパス含む)", "ファイル名"]

    df_diff = pd.merge(df_old, df_new, on=cols, how='outer', indicator=True, suffixes=('_旧', '_新'))

    #比較結果の判定
    def judge_diff(row):
        if row['_merge'] == 'right_only':
            return '追加'
        elif row['_merge'] == 'left_only':
            return '削除'
        elif row['_merge'] == 'both':
            if row['サイズ(KB)_旧'] != row['サイズ(KB)_新']:
                return '更新'
            else:
                return '変更なし'
        return '不明'

    #「比較結果」列を左端(インデックス0)に挿入
    df_diff.insert(0, '比較結果', df_diff.apply(judge_diff, axis=1))

    #不要な列の整理と出力
    df_final = df_diff.drop(columns=['_merge'])
    
    output_name = f"diff_report.csv"
    df_final.to_csv(output_name, index=False, encoding="utf-8-sig")

    print(f"比較完了!結果保存先: {output_name}")

if __name__ == "__main__":
    main()

3.コードのポイント

「差分を見るならWinMergeで十分では?」と思うかもしれません。しかし、インフラ実務ではPython自作ツールには以下の大きなメリットがあります。

並び順に左右されない: WinMergeなどのテキスト比較は1行ズレると崩れますが、Pythonは「ファイル名」をキーに突合するので、データの順序が変わっても正確に判定できます。

4.実行結果

5.まとめ

これまで比較ツールの定番としてWinMergeを愛用してきました。視覚的にどこが違うか一目でわかる便利さは、何物にも代えがたいものです。
しかし、数千、数万行におよぶファイルリストを扱う現場では、「行ズレ」が問題になってしまいます。
1行データが増減するだけで、意図しない場所で差異を誤認し、本来見つけるべき変化を見逃したりするリスクがありました。行数が多いほど、この「ズレの目視確認」は運用ミスの温床となってしまいます。
もし同じようにWinMergeの「ズレの目視確認」に限界を感じている方がいれば、ぜひこのPythonスクリプトを使ってみてください。

Discussion