python删除重复文件

article/2025/10/6 21:22:04

使用场景

网上爬取的图片重复量太大,需要删除重复图片。

环境

python 3
hashilib

分析一下这个问题:

首先,文件个数非常多,手工查找是不现实的,再说,单凭我们肉眼,在几千张图片或文件里面找到完全相同的难度也是很大的。所以要用程序实现。那么用程序怎么实现呢?根据什么判断两个文件完全相同呢?

  • 首先,根据文件名判断是靠不住的,因为文件名可以被随意更改,但文件内容不变。再说在同一个文件夹下面,也不可能出现两个完全相同的文件名,操作系统不允许的。
  • 还有一种方法就是根据文件大小来判断,这不失为一种好办法,但是,文件大小相同的图片可能不一样。再说图片一般都比较小,超过3M的基本没有,大部分不够1M,如果文件夹下面文件特别多,出现大小相同的的文件可能性是相当大的。所以单凭文件大小来比较不靠谱。
  • 还有一种方法是读取每张图片的内容,然后比较这个图片的内容和其他图片是否完全相同,如果内容相同那么这两张图片肯定是完全相同的。这种方法看起来是比较完美的,让我们来分析一下他的时空效率:首先每张图片的内容都要和其他图片进行比较,这就是一个二重循环,读取的效率低,比较的效率更低,所有的都比较下来是非常费时的!内存方面,如果预先把所有图片读取到内存可以加快文件的比较效率,但是普通计算机的内存资源有限,如果图片非常多,好几个G的话,都读到内存是不现实的。如果不把所有的文件读取到内存,那么每比较一次之前就要先读取文件内容,比较几次就要读取几次,从硬盘读取数据是比较慢的,这样做显然不合适。
  • 那么有没有更好的方法呢?我冥思苦想,绞尽脑汁,最后想到了md5。也许你会问,md5不是加密的吗?和我们的问题有关系吗?问得好!md5可以把任意长度的字符串进行加密后形成一个32的字符序列,包括数字和字母(大写或小写),因为字符串任何微小的变动都会导致md5序列改变,因此md5可以看作一个字符串的‘指纹’或者‘信息摘要’,因为md5字符串总共有36的32次方个,所以两个不同的字符串得到一个相同的md5概率是很小的,几乎为0,同样的道理,我们可以得到每个文件的md5,若干文件的md5相同的话就基本上可以肯定两个文件是相同的,因为md5相同而文件不同的概率太小了,基本可以忽略,这样我们就可以这样做:得到每个文件的md5,通过比较md5是否相同我们就可以确定两张图片是否相同。

下面是代码实现:

# -*- coding: cp936 -*-
import hashlib
import os
import timedef getmd5(filename):"""获取文件 md5 码:param filename: 文件路径:return: 文件 md5 码"""file_txt = open(filename, 'rb').read()# 调用一个md5对象m = hashlib.md5(file_txt)# hexdigest()方法来获取摘要(加密结果)return m.hexdigest()def main():# 文件夹路径path = input("path: ")# 存放文件的 md5 码all_md5 = []total_file = 0total_delete = 0# 开始时间start = time.time()# 遍历文件夹下的所有文件for file in os.listdir(path):# 文件数量加 1total_file += 1# 文件的路径real_path = os.path.join(path, file)# 判断文件是否是文件if os.path.isfile(real_path) == True:# 获取文件的md5码filemd5 = getmd5(real_path)# 如果文件 md5 已存在,则删除此文件if filemd5 in all_md5:total_delete += 1print('删除', file)else:# 如果文件 md5 不存在,则将此文件的 md5 码添加到 all_md5 列表中all_md5.append(filemd5)# 结束时间end = time.time()time_last = end - startprint('文件总数:', total_file)print('删除个数:', total_delete)print('耗时:', time_last, '秒')if __name__ == '__main__':main()

上面的程序原理很简单,就是依次读取每个文件,计算md5,如果md5在md5列表不存在,就把这个md5加到md5列表里面去,如果存在的话,我们就认为这个md5对应的文件已经出现过,这个图片就是多余的,然后我们就可以把这个图片删除了。下面是程序的运行截图:

我们可以看到,在这个文件夹下面有5235个文件,有144个是重复的,找到所有重复文件共耗时1.88秒。效率不算高,能不能进行优化呢?我分析了一下,我的程序里面有两个功能比较耗时间,一个是计算每个文件的md5,这个占了大部分时间,还有就是在列表中查找md5是否存在,也比较费时间的。从这两方面入手,我们可以进一步优化。

首先我想的是解决查找问题,或许我们可以对列表中的元素先排一下序,然后再去查找,但是列表是变化的,每次都排序的话效率就比较低了。我想的是利用字典进行优化。字典最显著的特点是一个key对应一个值我们可以把md5作为key,key对应的值就不需要了,在变化的情况下字典的查找效率比序列效率高,因为序列是无序的,而字典是有序的,查找起来当然更快。这样我们只要判断md5值是否在所有的key中就可以了。下面是改进后的代码:

# -*- coding: cp936 -*-
import hashlib
import os
import timedef getmd5(filename):"""获取文件 md5 码:param filename: 文件路径:return: 文件 md5 码"""file_txt = open(filename, 'rb').read()# 调用一个md5对象m = hashlib.md5(file_txt)# hexdigest()方法来获取摘要(加密结果)return m.hexdigest()def main():# 文件夹路径path = input("path: ")# 存放文件的 md5 码all_md5 = {}  # 改为字典total_file = 0total_delete = 0# 开始时间start = time.time()# 遍历文件夹下的所有文件for file in os.listdir(path):# 文件数量加 1total_file += 1# 文件的路径real_path = os.path.join(path, file)# 判断文件是否是文件if os.path.isfile(real_path) == True:# 获取文件的md5码filemd5 = getmd5(real_path)# 如果文件 md5 已存在,则删除此文件if filemd5 in all_md5.keys():  # 字典的键为文件 md5 码total_delete += 1print('删除', file)else:# 如果文件 md5 不存在,则将此文件的 md5 码添加到 all_md5 字典中all_md5[filemd5] = ""# 结束时间end = time.time()time_last = end - startprint('文件总数:', total_file)print('删除个数:', total_delete)print('耗时:', time_last, '秒')if __name__ == '__main__':main()

再看看运行截图:

从时间上看,确实比原来快了一点,但是还不理想。下面还要进行优化。还有什么可以优化呢?md5!上面的程序,每个文件都要计算md5,非常费时间,是不是每个文件都需要计算md5呢?能不能想办法减少md5的计算次数呢?我想到了一种方法:上面分析时我们提到,可以通过比较文件大小的方式来判断图片是否完全相同,速度快,但是这种方法是不准确的,md5是准确的,我们能不能把两者结合一下?答案是肯定的。我们可以认定:如果两个文件完全相同,那么这两个文件的大小和md5一定相同,如果两个文件的大小不同,那么这两个文件肯定不同!这样的话,我们只需要先查看文件的大小是否存在在size字典中,如果不存在,就将它加入到size字典中,如果大小存在的话,这说明有至少两张图片大小相同,那么我们只要计算文件大小相同的文件的md5,如果md5相同,那么这两个文件肯定完全一样,我们可以删除,如果md5不同,我们把它加到列表里面,避免重复计算md5。具体代码实现如下(最终版本):

# -*- coding: cp936 -*-
import hashlib
import os
import timedef getmd5(filename):"""获取文件 md5 码:param filename: 文件路径:return: 文件 md5 码"""file_txt = open(filename, 'rb').read()# 调用一个md5对象m = hashlib.md5(file_txt)# hexdigest()方法来获取摘要(加密结果)return m.hexdigest()def main():# 文件夹路径path = input("path: ")# 键为文件大小, 值为列表(文件路径、md5)all_size = {}total_file = 0total_delete = 0# 开始时间start = time.time()# 遍历文件夹下的所有文件for file in os.listdir(path):# 文件数量加 1total_file += 1# 文件的路径real_path = os.path.join(path, file)# 判断文件是否是文件if os.path.isfile(real_path) == True:# 获取文件大小size = os.stat(real_path).st_size# md5(默认为空)size_and_md5 = [""]# 如果文件大小已存在if size in all_size.keys():# 获取文件的md5码new_md5 = getmd5(real_path)# 大小相同,md5 为空,添加md5if all_size[size][0] == "":all_size[size][0] = new_md5# md5 已存在,删除if new_md5 in all_size[size]:print('删除', real_path)# os.remove(real_path)total_delete += 1else:# md5 不存在,进行添加all_size[size].append(new_md5)else:# 如果文件大小不存在,则将此文件大小添加到 all_size 字典中all_size[size] = size_and_md5# 结束时间end = time.time()time_last = end - startprint('文件总数:', total_file)print('删除个数:', total_delete)print('耗时:', time_last, '秒')if __name__ == '__main__':main()

时间效率怎样呢?看下图:

只用了0.5秒!比前两个效率提高了好几倍!


http://chatgpt.dhexx.cn/article/DR8xv25C.shtml

相关文章

工具及方法 - 使用Total Commander来查找重名文件

我只是一个Total Commander的轻度使用者,主要使用的是打开多个窗口,可以方便的以标签形式切换。 还有,这个软件是免费的,只是免费版打开时多一步,要输入个数字验证。 今天在使用一个SDK时,要包含进很多头文…

在群晖中批量删除重复文件

安装“存储空间分析器”套件配置“重复文件候选”报告,并生成报告查看并下载报告用excel打开报告并筛选出需要删除的文件 IF(A2A1,1,"")上传文件到群晖,并配置计划任务 cat 文件路径 | xargs -I {} rm -f "{}"执行并删除计划任务提醒…

在 QNAP(威联通)NAS 上自动查找和删除 重复文件 的方法

Qidi 2020.12.12 0. 前言 看到很多人说在 QNAP NAS 上使用 fdupes 工具只能实现查找重复文件的效果,要删除文件只能对照生成的重复文件列表手动操作。这个说法其实是不对的,fdupes 完全支持自动去重功能。 以下正文说明了使用 fdupes 工具自动查找并删…

硬盘快满了,怎么办?查找重复文件

硬盘快满了,怎么办?查找重复文件,绿色版 链接:https://pan.baidu.com/s/1nbhRhninawNLK5CHZfanWA 提取码:yu37 序列号 TDFP-XWAL-EPNX-ALWN-LLLLLL 它非常易于使用,只需要选择资源(驱动器&…

重复文件查找工具

电脑在经过长时间的使用后,会存在着大量重复的无用文件,这些文件会占用我们电脑中有限的磁盘空间,虽然现在我们的磁盘空间都是够大了,这些重复文件也许不算什么,但是它们会影响到系统的效能,并且我们还是要…

计算机一级查找同类型文件,如何快捷找出电脑内的重复文件

有时特喜欢收集各种软件和资料,但是时间久了,很多软件和资料之前下载过了,后来不记得了,又下载了,这样重复的非常多。这样重复的文件多了,占了大量的磁盘空间,也影响电脑运行性能,当…

怎么快速查找重复文件以及删除重复文件

多余的重复文件可能会浪费大量的硬盘存储空间,久而久之,电脑内存就会不够用,uplicate Finder and Remover for Mac是一款功能强大且操作简单的软件,如果您想要快速找出重复文件,节省磁盘空间,装机必备软件。…

mac电脑重复文件如何查找?

当我们的MAC电脑提示你磁盘空间已满时可以通过在Mac上删除不必要的重复文件,文件夹和类似照片,可以获得更多可用磁盘空间,Duplicate File Finder for Mac是一款功能强大的重复文件查找软件。Duplicate File Finder for Mac可处理图像,视频,音乐,文档,文件夹等等。它允许…

如何查找重复文件并快速删除,电脑查重复文件的方法

在日常使用电脑的过程中,我们要下载、编辑、保存文件,难免会出现一些重复文件,这些重复文件不仅会给工作带来不便,也会占用硬盘宝贵的空间。因此,经常查找与清理电脑中的重复文件就显得格外重要。如何查找重复文件并快…

jquery.orgchart.js 简单demo,自定义内容,自定义事件

orgchart简单demo GIT地址&#xff1a; https://github.com/Vlovely/orgchartDemo.git 预览图 代码示例 <!DOCTYPE html> <html lang"en"> <head><meta charset"utf-8"><title>Organization Chart Plugin</title>&…

html 组织结构 图表,OrgChart-简单实用的组织结构图表jQuery插件

OrgChart是一款简单实用的组织结构图表jQuery插件。OrgChart通过DOM元素,jQuery和CSS3过渡效果来制作组织结构图表。可以使用本地数据,或通过ajax调用来完成数据的填充。 使用方法 使用OrgChart组织结构图表插件需要在页面中引入jquery.orgchart.css,jquery和html2canvas.js…

html5控件结构图,OrgChart组织架构图控件

插件描述:jQuery OrgChart 是一个用来绘制组织结构图的 jQuery 插件。 可以自己定加载自己想要的组织架构,通过json的形式 该插件为画组织架构图插件,通过OrgChart API定义的数据接口以json的数据形式将自己想要的组织架构数据传给orgChart,上手难度低,可扩展性比较高。 从…

使用vue-orgchart库来创建组织架构图

在这篇博客中&#xff0c;将详细介绍如何构建一个使用Vue.js和vue-orgchart的组织架构图Demo。Vue.js是一种构建用户界面的JavaScript框架&#xff0c;而vue-orgchart是一个基于Vue的组织结构图组件。本Demo将展示如何使用这两种技术来创建一个展示组织架构的可视化工具。 页面…

JQ插件OrgChart实现组织结构图

最近在做一个OA系统的组织结构图&#xff0c;需求如下。 第一眼看起来让人联想到脑图&#xff0c;思维导图大家都比较熟悉。但这不是脑图&#xff0c;是组织结构图。有添加&#xff0c;编辑&#xff0c;删除等功能… 随后我就找了一些插件&#xff1a; 1、jsMind&#xff08;…

使用OrgChart技术流程图(树状图)

基于OrgChart技术流程图[树状图] 一.实现效果图二.数据集三.实现思路1.创建数据封装函数2.将现有的数据处理成json数组3.调用closureProcessing()函数,将json数组变为json字符串4.初始化画布,并设置数据 四.源码1.HTML部分源码(即展示树状图用的画布容器)2.CSS部分的样式代码3.…

vue-orgchart 实现节点的增 删 改 功能

UI框架是 ant-design-vue 导出图片我是自己重新写的&#xff0c;要下载 html2canvas vue-orgchart 属性说明 在 这篇文章中https://blog.csdn.net/weixin_44164867/article/details/110871475 https://balkan.app/OrgChartJS-Demos/ 官网有好多例子可以使用 <template>…

最需要的时候遇见你OrgChart

聊聊OrgChart 使用&#xff0c;优雅的方式为你展现舒服的组织架构图&#xff0c; 前言 闲来无事写一个多级用户关系层&#xff0c;于是就存在展示的问题。这时OrgChart就派上了用场。 在用的过程中&#xff0c;有一耐耐的小问题&#xff0c;咔咔就借着问题点&#xff0c;给大…

使用OrgChart插件生成家谱组织结构图

1.orgchart插件&#xff1a; github地址&#xff1a;https://github.com/dabeng/OrgChart 2.前端代码&#xff1a; //1.加载树形数据&#xff1a;ajax请求获取json格式的数据&#xff08;flag参数可以无视&#xff0c;我自己的业务逻辑需要&#xff09;function setTreeInfo(fl…

OrgChart页面模仿编程简单记录

OrgChart页面模仿编程简单记录 导航栏 整体来看&#xff0c;导航栏设计的还是比较简洁&#xff0c;顶部有8个导航模块&#xff0c;每个模块点击后会跳转到相应模块页面。可以使用在App.js页面中使用<Router> <Navlink>来实现。 <Router> <nav> <…

如何在react中使用OrgChart?

最近在将OrgChart嵌入至React时&#xff0c;碰见了一些坑&#xff0c;希望能以此记录我是怎么爬出来的~ 一、什么是OrgChart&#xff1f; 一款基于jquery来画组织架构图的插件。有以下特点&#xff1a; 支持本地数据和远程数据&#xff08;JSON&#xff09;基于CSS3转换的平滑…