ハッシュ比較は「ファイルの中身が本当に同じか」を正確に判断するための最重要テクニック
ファイル名が同じでも中身が違うことはあります。
サイズが同じでも中身が違うこともあります。
しかし ハッシュ(SHA-256 など) を使えば、ファイルの内容を数学的に要約した値を比較できるため、完全一致かどうかを高精度で判定できます。
業務では次のような場面で必須になります。
- バックアップ後に「正しくコピーできたか」検証したい
- 重複ファイルを正確に検出したい
- ダウンロードしたファイルが壊れていないか確認したい
- システム間でファイルの整合性をチェックしたい
ここから、初心者でも理解しやすいように、基本 → 応用 → 実務テンプレートの順で丁寧に解説します。
ハッシュ比較の基本:SHA-256 でファイルの内容を数値化する
最小構成:ファイルのハッシュ値を取得する
import hashlib
def file_hash(path, chunk_size=1024 * 1024):
h = hashlib.sha256()
with open(path, "rb") as f:
while chunk := f.read(chunk_size):
h.update(chunk)
return h.hexdigest()
print(file_hash("data.txt"))
Python深掘りポイント
"rb"でバイナリ読み込みするのは「テキストかどうかに関係なく正確に読むため」chunk_sizeを使うことで大容量ファイルでもメモリ不足にならないhexdigest()はハッシュ値を 16 進数の文字列で返す
2つのファイルを比較して「完全一致」か判定する
ハッシュ値を比較するだけで一致判定ができる
h1 = file_hash("file_a.dat")
h2 = file_hash("file_b.dat")
if h1 == h2:
print("完全一致:内容が同じです")
else:
print("不一致:内容が異なります")
Python深掘りポイント
- ハッシュが一致する=内容が完全に同じ
- サイズや名前ではなく「中身」で比較するため信頼性が高い
- バックアップ検証で非常に重要
例題①:バックアップ後に「コピー成功」をハッシュで検証する
シナリオ
bigfile.dat をコピーした後、本当に同じか確認したい。
import shutil
src = "bigfile.dat"
dst = "backup/bigfile.dat"
shutil.copy2(src, dst)
if file_hash(src) == file_hash(dst):
print("コピー成功:内容一致")
else:
print("コピー失敗:内容が異なります")
Python深掘りポイント
- 大容量ファイルでは「コピー成功したように見えて壊れている」ことがある
- ハッシュ比較はその不安を完全に解消する
例題②:フォルダ内の重複ファイルをハッシュで検出する
シナリオ
同じ内容のファイルが複数あるフォルダを整理したい。
import os
def find_duplicates(folder):
hashes = {}
duplicates = []
for name in os.listdir(folder):
path = os.path.join(folder, name)
if os.path.isfile(path):
h = file_hash(path)
if h in hashes:
duplicates.append((hashes[h], path))
else:
hashes[h] = path
return duplicates
dups = find_duplicates("data")
for a, b in dups:
print("重複:", a, "<->", b)
Python深掘りポイント
- サイズ一致よりも精度が高い
- 名前が違っても内容が同じなら検出できる
- 容量削減に直結する
例題③:ダウンロードしたファイルが壊れていないか検証する
シナリオ
配布元が公開しているハッシュ値と一致するか確認したい。
expected = "d2c7e4a1f8b0..." # 公開されているハッシュ値
actual = file_hash("download.zip")
if expected == actual:
print("正常:ファイルは破損していません")
else:
print("警告:ファイルが破損している可能性があります")
Python深掘りポイント
- ソフトウェア配布ではハッシュ値が公開されていることが多い
- セキュリティ上も重要(改ざん検知)
例題④:サブフォルダも含めてフォルダ全体のハッシュ比較を行う
シナリオ
2つのフォルダが完全に同じか確認したい。
import os
def folder_hashes(folder):
result = {}
for current, dirs, files in os.walk(folder):
for name in files:
path = os.path.join(current, name)
rel = os.path.relpath(path, folder)
result[rel] = file_hash(path)
return result
h1 = folder_hashes("folder_a")
h2 = folder_hashes("folder_b")
if h1 == h2:
print("フォルダ内容が完全一致")
else:
print("フォルダ内容が異なります")
Python深掘りポイント
- 相対パスをキーにすることでフォルダ構造ごと比較できる
- バックアップフォルダの検証に最適
pathlib を使った読みやすいハッシュ比較
Path オブジェクトで直感的に書ける
from pathlib import Path
import hashlib
def file_hash_path(p: Path):
h = hashlib.sha256()
with p.open("rb") as f:
while chunk := f.read(1024 * 1024):
h.update(chunk)
return h.hexdigest()
p1 = Path("file_a.txt")
p2 = Path("file_b.txt")
print("一致" if file_hash_path(p1) == file_hash_path(p2) else "不一致")
Pythonメリット
p.open()が読みやすい- パス結合が
/で直感的 - 大規模コードでも保守性が高い
ハッシュ比較を業務で使うときの重要ポイント
- SHA-256 は精度が高く、実務で最も使われる
- 大容量ファイルはチャンク読み込みでメモリ節約
- コピー後の検証に使うと信頼性が大幅に向上
- 重複ファイル検出にも応用できる
- フォルダ単位の整合性チェックも可能
- セキュリティ(改ざん検知)にも役立つ
