You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复Python MD5计算逻辑,使相同图片文件返回一致MD5值?

问题

参考Stack Overflow上的文件MD5计算方法,编写了一个移除dst_dir目录中重复文件的脚本,但大量.jpg和.mp4文件无法被MD5识别为重复项。排查相关方法后无效,怀疑是文件附加属性(如修改日期)变更导致,以下是原代码:

import os
dst_dir="/"
import hashlib

directory=dst_dir;
#list of file md5
md5_list=[];
md5_file_list=[];


for root, subdirectories, files in os.walk(directory):
    
    if ".tresorit" not in root:
        for file in files:
            file_path =os.path.abspath( os.path.join(root,file) );
            print(file_path)

            # Open,close, read file and calculate MD5 on its contents 
            with open(file_path, 'rb') as file_to_check:
                # read contents of the file
                data = file_to_check.read()    
                # pipe contents of the file through
                md5_returned = hashlib.md5(data).hexdigest()

            if md5_returned not in md5_list:
                md5_list.append(md5_returned);
                md5_file_list.append(file_path);
                
            else:
                # remove duplicate file 
                
                print(["Duplicate file", file_path, md5_returned] )
                if "-" not in file:
                    os.remove(file_path);
                    print("Duplicate file removed 01")
                else:
                    file_list_index=md5_list.index(md5_returned);
                    
                    if "-" not in md5_file_list[file_list_index]:
                        os.remove(md5_file_list[file_list_index]);
                        
                        del md5_list[file_list_index]
                        del md5_file_list[file_list_index]
                        print("Duplicate file removed 02")
                        
                        md5_list.append(md5_returned)
                        md5_file_list.append(file_path)
                    else:
                        os.remove(file_path);
                        print("Duplicate file removed 03")
修复方案

先明确:MD5计算的是文件内容的哈希值,文件附加属性(修改时间、权限等)不会影响MD5结果,问题出在原代码的文件读取逻辑和数据存储方式上。以下是具体修复:

核心问题点

  1. 大文件读取不完整:原代码直接用read()把整个文件加载到内存,对大体积的.mp4或高清.jpg来说,可能出现内存溢出或读取截断,导致MD5计算错误。
  2. 列表查找效率极低:用列表存储MD5值,每次判断重复都要遍历整个列表,文件数量多的时候会卡顿甚至出错。
  3. 重复处理逻辑混乱:原代码中基于文件名含-的判断逻辑绕来绕去,容易出现误删或漏删的情况。

修复后的代码

import os
import hashlib

def calculate_md5(file_path, chunk_size=4096):
    """分块计算文件MD5,适配大文件,避免内存溢出"""
    md5 = hashlib.md5()
    with open(file_path, 'rb') as f:
        # 分块读取文件,每次读4096字节
        while chunk := f.read(chunk_size):
            md5.update(chunk)
    return md5.hexdigest()

dst_dir = "/"
# 用字典存储MD5与文件路径的映射,键为MD5值,值为对应的文件路径
md5_file_map = {}

for root, _, files in os.walk(dst_dir):
    # 跳过.tresorit目录
    if ".tresorit" in root:
        continue
    for file in files:
        file_path = os.path.abspath(os.path.join(root, file))
        print(f"正在处理: {file_path}")
        
        try:
            # 计算当前文件的MD5
            file_md5 = calculate_md5(file_path)
        except Exception as e:
            print(f"计算MD5失败: {file_path} - {str(e)}")
            continue
        
        if file_md5 not in md5_file_map:
            # 首次出现该MD5,记录路径
            md5_file_map[file_md5] = file_path
        else:
            # 发现重复文件,按规则处理
            print(f"找到重复文件: {file_path} (MD5: {file_md5})")
            # 自定义保留规则:优先保留不含"-"的文件
            if "-" not in file:
                # 删除已记录的旧文件,替换为当前文件
                os.remove(md5_file_map[file_md5])
                print(f"已删除旧重复文件: {md5_file_map[file_md5]}")
                md5_file_map[file_md5] = file_path
            else:
                # 删除当前文件,保留已记录的文件
                os.remove(file_path)
                print(f"已删除当前重复文件: {file_path}")

关键优化说明

  • 分块计算MD5:通过分块读取文件,不管文件多大都能完整计算哈希,避免大文件导致的内存问题,这是解决图片、视频文件MD5计算错误的核心。
  • 字典存储映射:字典的键查找是O(1)复杂度,处理成千上万个文件时,速度比列表快几个数量级。
  • 简化处理逻辑:明确重复文件的保留规则,避免原代码中复杂的列表删除、插入操作,减少出错概率。
  • 异常捕获:处理文件读取时的权限问题、文件损坏等异常,确保脚本不会中途崩溃。

内容的提问来源于stack exchange,提问作者ShoutOutAndCalculate

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 09:27:48