How to Find Duplicate Files by Size and Hash in Python

Recursively scan a directory, group files by size, then hash candidates to identify exact duplicate files.

Medium Python 3.8+ Aug 9, 2026 Files & data 17 views 0 copies

Python code

40 lines
Python 3.8+
import hashlib
from pathlib import Path

def hash_file(path, chunk_size=8192):
    hasher = hashlib.md5()
    with open(path, 'rb') as f:
        while chunk := f.read(chunk_size):
            hasher.update(chunk)
    return hasher.hexdigest()

def find_duplicates(directory):
    size_map = {}
    for path in Path(directory).rglob('*'):
        if path.is_file():
            size = path.stat().st_size
            size_map.setdefault(size, []).append(path)
    
    hash_map = {}
    for size, paths in size_map.items():
        if len(paths) > 1:
            for path in paths:
                file_hash = hash_file(path)
                hash_map.setdefault((size, file_hash), []).append(path)
    
    duplicates = []
    for paths in hash_map.values():
        if len(paths) > 1:
            duplicates.append(paths)
    return duplicates

if __name__ == "__main__":
    test_dir = Path("/tmp/test_duplicates")
    test_dir.mkdir(exist_ok=True)
    (test_dir / "file1.txt").write_text("same content")
    (test_dir / "file2.txt").write_text("same content")
    (test_dir / "file3.txt").write_text("different")
    
    result = find_duplicates(test_dir)
    for group in result:
        print([str(p) for p in group])

Output

stdout
['/tmp/test_duplicates/file1.txt', '/tmp/test_duplicates/file2.txt']

How it works

The script first groups all files by their size using a dictionary, which quickly narrows down potential duplicates. Only groups with more than one file are hashed, avoiding costly MD5 computation for unique sizes. The hash_file function reads files in chunks to handle large files without loading them entirely into memory. Files with the same size and identical hash are considered duplicates and grouped together. Using Path.rglob allows recursive traversal of subdirectories.

Common mistakes

  • Hashing every file without pre-filtering by size, wasting I/O and CPU
  • Ignoring symlinks, which may cause the same file to be counted twice
  • Not handling permission errors when reading files
  • Forgetting that files with zero size are all duplicates but hashing them is fine

Variations

  1. Use SHA-256 instead of MD5 for stronger collision resistance: `hashlib.sha256()`
  2. Return a dictionary mapping hash to list of paths instead of list of groups

Real-world use cases

  • Cleaning up redundant copies in a photo library to free disk space.
  • Identifying duplicate configuration files across multiple services in a repo.
  • Detecting accidental file copies in a data pipeline before processing.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Files & data

Related tutorials and quizzes for this topic.