扫描并清除重复文件的Python脚本

发布时间 2023-12-11 15:42:41作者: fmcdr

电脑里存的照片越来越多,其中有很多是重复的。如果依赖人边去一张一张对比,需要的工作量太大了。

下面的Python脚本在一个目录树上递归地对所有文件作MD5校验,将重复的文件找出来。保留用户指定的文件,将多余的文件全部删除掉。

#!/usr/bin/env python3

import sys
import hashlib
import os

POOL = {}

def md5_hash(fname):
    with open(fname, 'rb') as f:
        data = f.read()
        return hashlib.md5(data).hexdigest()


def handle_file(fname):
    hash = md5_hash(fname)
    t = POOL.get(hash)
    if t:
        POOL[hash].append(fname)
    else:
        POOL[hash] = [fname]
    
def walk_dir(directory, fun):
    files = os.listdir(directory)
    for f in files:
        path = os.path.join(directory, f)
        if os.path.isdir(path):
            walk_dir(path, fun)
        else:
            fun(path)
    
if __name__ == '__main__':
    if len(sys.argv) > 1:
        directory = sys.argv[1]
    else:
        directory = '.'
        
    # scan the directory
    walk_dir(directory, handle_file)
    
    for hash, file_list in POOL.items():
        if len(file_list) > 1:
            print()
            for i in range(len(file_list)):
                print(f"{i} - {file_list[i]}")
            select = input('\n以上文件重复,请输入要保留的编号\nA.全部保留, Q.退出, 默认保留第 0 个: ') or '0'
            if select.upper() == 'A':
                continue
            if select.upper() == 'Q':
                sys.exit(0)
            keep = int(select)
            for i in range(len(file_list)):
                if i != keep:
                    os.remove(file_list[i])
    print('Success')

所有的文件散列值都保存在内存中,只有在所有文件都扫描完成后才会有结果。所以,如果你试图用它去扫描一个很巨大的目录树,您就慢慢等吧!

吐槽一下现在的手机系统,我的重复文件绝大部分来源于手机。通常是云空间或者是微信贡献的。特别是微信对存储空间的浪费,简直令人发指。

最后,脚本的交互似乎需要改进。对于每一组重复的文件都需要用户指定要保留的文件。这是我自己的需要决定的。其他人可能并不在意要保留哪个文件,只需要任意保留一个副本即可。对于这些用户,可以一直按回车就行了。我不想把程序的逻辑搞复杂。