資料の名前が違っていても、中身が同じコピーということがあります。a.txtとaのコピー.txtのような名前だけで判定すると、少し修正した別版まで同じと考えてしまうかもしれません。
Pythonでは、まずサイズが同じファイルを候補にし、その中でSHA-256を比べる方法があります。SHA-256は内容のバイト列から求める要約値です。候補を出す処理と、どれを残すかの判断は分けます。
サイズで絞って内容を順に読む
次の例は一時フォルダーへ三つの練習用ファイルを作ります。a.txtとcopy.txtは同じ内容、other.txtは同じ長さの別内容です。利用者の資料フォルダーは読みません。
from collections import defaultdict
from hashlib import sha256
from pathlib import Path
from tempfile import TemporaryDirectory
def digest(path):
result = sha256()
with path.open("rb") as stream:
while block := stream.read(1024 * 1024):
result.update(block)
return result.hexdigest()
with TemporaryDirectory() as directory:
folder = Path(directory)
for name, content in {
"a.txt": b"same\n", "copy.txt": b"same\n", "other.txt": b"diff\n"
}.items():
(folder / name).write_bytes(content)
by_size = defaultdict(list)
for path in sorted(folder.iterdir()):
if path.is_file() and not path.is_symlink():
by_size[path.stat().st_size].append(path)
by_digest = defaultdict(list)
for candidates in by_size.values():
if len(candidates) > 1:
for path in candidates:
by_digest[digest(path)].append(path.name)
groups = sorted(sorted(names) for names in by_digest.values() if len(names) > 1)
print("同じ内容の候補:", groups)
print("元ファイルの数:", len(list(folder.iterdir())))
assert groups == [["a.txt", "copy.txt"]]
assert len(list(folder.iterdir())) == 3
候補にはa.txtとcopy.txtだけが出て、元の三ファイルは残ります。Windows・Python 3.12.10で、この結果を確認しました。ファイル全体をread_bytesで一度に読み込まず、一定量ずつハッシュへ渡しています。
同じサイズだけでは決めない
other.txtも同じサイズですが、中身は違うため同じグループへ入りません。サイズによる分類は内容を読む対象を減らすための前段です。サイズの一致だけを重複と呼ばないようにします。
反対に、PDFの見た目が同じでも、作成日時などの内部情報が違えばファイルのバイト列は異なり、ハッシュも変わります。画像や文書を見た目で比較する機能とは違います。
走査する範囲と更新中の扱い
この例は指定フォルダー直下だけを見ており、サブフォルダーへは入りません。実際の対象を増やすなら、共有先、アクセス権、除外フォルダー、リンクを追うかを先に決めます。
読み込んでいる間にファイルが変更されると、サイズを見た時点と内容を読んだ時点が違う状態になる可能性があります。更新中のファイルを確定版の同一性確認として扱わず、取り込み済みのコピーなど、安定した対象で比較します。
ハッシュには衝突の可能性もあるため、重要な資料を消す判断では必要な追加確認を行います。候補一覧へ元のパス、サイズ、確認日時を残し、残す版と参照先を確かめてから整理してください。このコードには削除や移動を入れていません。
ファイルの読み方はPythonのファイル読み書き、名前を整理する前の確認は一括リネームの基本で補えます。
参考資料
Python hashlibとtempfileの公式資料を2026年11月1日に確認しました。
