Python高效率遍历文件夹寻找重复文件

基本需求

  1. 把文件夹中的重复文件找出来
  2. 找出来之后用csv输出,左边是源文件,右边是重复文件
  3. 效率不能差,不能直接撑爆内存,不能占用过多资源
  4. 检测的文件夹和存放csv的地方可以自己定义,加上终端交互
  5. 重复文件筛选支持md5,大小等方式

需求分析

首先要分析一点,就是我们该如何去做重复文件的对比,并且效率还要高,首先网上过多的递归,os.walk的方法不可用,因为他们都会把遍历到的内容直接做成一个大列表,塞到内存里面,数据量大很容易爆掉,并且还要进行MD5,或者是大小比对,这个就非常难缠了。

基础想法

其实说白了,拿到所有文件列表file_list,把文件依次对比,这里我们可以用dict,分两种情况
按照文件名和大小

设定两个dict,例如record和dup,遍历file_list,生成一个数组,比对其中的文件名和大小
按照大小和MD5值

设定两个dict,例如record和dup,遍历file_list,生成一个数组,比对其中的md5值和大小

具体代码

闲话休提,我们开始写代码吧

定义遍历函数代码

首先定义遍历文件夹的部分diskwalk.py

# coding: utf-8

__author__ = "lau.wenbo"


import os,sys


class diskwalk(object):
    def __init__(self, path):
        self.path = path
    def paths(self):
        path = self.path
        # 这里用了一个迭代器逻辑,防止所有数据塞内存爆掉
        path_collection = (os.path.join(root,fn) for root,dirs,files in os.walk(path) for fn in files)
        return path_collection

定义检查md5值代码

接着我们定义检查md5值的一个逻辑checksum.py

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
# coding: utf-8

__author__ = "lau.wenbo"

import hashlib,sys

# 分块读MD,速度快

def create_checksum(path):
    fp = open(path)
    checksum = hashlib.md5()
    while True:
        buffer = fp.read(8192)
        if not buffer: break
        checksum.update(buffer)
    fp.close()
    checksum = checksum.digest()
    return checksum

定义主函数代码

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
# coding: utf-8

__author__ = "lau.wenbo"


from checksum import create_checksum
from diskwalk import diskwalk
from os.path import getsize
import csv
import os
import sys
reload(sys)
sys.setdefaultencoding('utf8')


def findDupes(path):
    record = {}
    dup = {}
    d = diskwalk(path)
    files = d.paths()
    for file in files:
        try:
            # 这里使用了大小,文件名的对比方式,如果你需要MD5值的对比方式,可以打开下面的注释
            #compound_key = (getsize(file),create_checksum(file))
            compound_key = (getsize(file), file.split("/")[-1])
            if compound_key in record:
                dup[file] = record[compound_key]
            else:
                record[compound_key]=file
        except:
            continue
    return dup


if __name__ == '__main__':
    path = sys.argv[1]
    csv_path = sys.argv[2]
    if not os.path.isdir(path) or not os.path.isdir(csv_path) or csv_path[-1] != "/":
        print u"参数不是一个有效的文件夹!"
        exit()
    else:
        path = path.decode("utf-8")
        print u"待检测的文件夹为{path}".format(path=path)
        with open(u"{csv_path}重复文件.csv".format(csv_path=csv_path),"w+") as csvfile:
            # 源文件 重复文件
            header = ["Source", "Duplicate"]
            writer = csv.DictWriter(csvfile, fieldnames=header)
            writer.writeheader()
            print u"开始遍历文件夹,寻找重复文件,请等待........."
            print u"开始写入CSV文件,请等待........"
            for file in findDupes(path).items():
                writer.writerow({"Source":file[1],"Duplicate":file[0]})

结语

实现了哪些功能呢,哈哈,结尾来说一下,其实核心就是我用了一个列表生成器,加了一个迭代器,迭代器可是好东西,不会撑内存,不错了,效率也还可以,200w数据判定也就20多分钟,支持大数据量

posted @   I'm_江河湖海  阅读(4)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示