Python 如何实现文件自动去重

Python 文件自动去重

平日里一来无聊,二来手巧,果然下载了好多无(luan)比(qi)珍(ba)贵(zao)的资料,搞得我小小的硬盘(已经扩到6T了)捉襟见肘,

有次无意间,发现有两个居然长得一毛一样,在房子这么小的情况下,我怎能忍两个一毛一样的东西不要脸皮的躺在我的硬盘里,果断搞掉一个,整理一下,本来想文件名一样的就保留一份,但问题出现了,居然有名字一样,内容却完全不一样的文件,想我背朝黄土面朝天吹着空调吃着西瓜下载下来的东西,删除是不可能的,这辈子都是不可能删除的。可是我也又不能把这数以亿计的文件挨个打开看看里面一样不一样吧,这个工程我大概够我做了好久好久了,有没有办法搞个软件帮帮我呢,答案是肯定的,要不然我也不用在这里写这个博客了(应该是苦逼的一个一个打开比较吧),说正题,Python提供了一个比较文件内容的东西,那就是。。。。。。。。。。哈希算法

MD5消息摘要算法(英语:MD5 Message-Digest Algorithm),一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。MD5由美国密码学家罗纳德·李维斯特(Ronald Linn Rivest)设计,于1992年公开,用以取代MD4算法。

说了这么长,总结出来就一句,这玩意就是文件的指纹,几乎每个文件是唯一的(碰到重复的,恭喜你,可以去买彩票了),那我们就把这个指纹拿出来,一个一个比对,肯定不能会有漏网的文件,既不会错杀三千,也不使一文件漏网,原理上通了,那么我们就要去搞个代码来帮我完成这个工作,作为最好用的语言,Python就这样被我翻了牌子

# -*- coding:utf-8 -*-
import os
import hashlib
import time
import sys
#搞到文件的MD5
def get_ms5(filename):
    m = hashlib.md5()
    mfile = open(filename , "rb")
    m.update(mfile.read())
    mfile.close()
    md5_value = m.hexdigest()
    return md5_value
#搞到文件的列表
def get_urllist():
    base = ("D:\\lwj\\spider\\pic\\")#这里就是你要清缴的文件们了
    list = os.listdir(base)
    urllist = []
    for i in list:
        url = base + i
        urllist.append(url)

    return urllist
#主函数
if __name__ == '__main__':
    md5list = []
    urllist = get_urllist()
    print("test1")
    for a in urllist:
        md5 = get_ms5(a)
        if(md5 in md5list):
            os.remove(a)
            print("重复:%s" % a)
        else:
            md5list.append(md5)
            print("一共%s张照片" % len(md5list))

效果

python3 大文件去重

一、生成待去重数据

每行是固定位数的数字串

import os
from random import randint
#-- from u_工具 import *
print("———— 开始 ————")
#-- 打点()

# 用来配置的变量
位数 = 13
行数 = 500 * 10000

输出目录 = "./a_输入"
输出文件 = f"{输出目录}/随机数.txt"

# 预处理
_00 = "".join(["0" for i in range(位数 - 1)])
_100 = "1" + _00
最小值 = int(_100)
_1000 = _100 + "0"
最大值 = int(_1000)

if not os.path.exists(输出目录):
    os.makedirs(输出目录)
#-- 输出文件 = 文件名防重_追加数字(输出文件)

# 实际处理
with open(输出文件,"a") as f:
    for i in range(行数):

        f.write(f"{randint(最小值, 最大值)}\n")

        百分比 = (i+1) / 行数 * 100
        if 百分比 == int(百分比):
            print(f"已完成{int(百分比)}%")
#-- 打点()
#-- print(f"\n总耗时:{计时(0)}")
print("———— 结束 ————")

二、通过set按行去重

1. 按原值比较

(1)读取全部数据

(2)用split来分行

(3)通过set数据结构来去除重复数据

(4)将set的数据写入文件

import os
#-- from u_工具 import *
print("———— 开始 ————")
#-- 打点()

# 用来配置的变量
输入目录 = "./a_输入"
输出目录 = "./b_输出"
输出文件 = f"{输出目录}/去重结果.txt"
# 预处理
# 目录不存在就手动建立
if not os.path.exists(输出目录):
    os.makedirs(输出目录)
if not os.path.exists(输入目录):
    os.makedirs(输入目录)
#-- 输出文件 = 文件名防重_追加数字(输出文件)

# 获取待去重文件
待去重文件列表 = []
待去重文件列表 = [f"{输入目录}/{i}" for i in os.listdir(输入目录)]
#-- getDeepFilePaths(待去重文件列表,输入目录,"txt")
print(f"\n总共{len(待去重文件列表)}个文件")

换行符 = b"\n"
if platform.system().lower() == 'windows':
    换行符 = b"\r\n"

# 实际处理
all_lines = []
文件个数 = 0
for 文件 in 待去重文件列表:
    文件个数 += 1
    print(f"\n处理第{文件个数}个文件")

    #-- 打点()
    # (1)读全部
    with open(文件, "rb") as f:
        data = f.read()

    # (2)split分行
    lines = data.split(换行符)
    all_lines.extend(lines)
    #-- 打点()
    #-- print(f"分行完毕,耗时:{计时()}")

# (3)集合去重
all_lines_set = set(all_lines)
all_lines_set.remove(b"")
#-- 打点()
#-- print(f"\n\n去重完毕,耗时:{计时()}")

# (4)循环写入
with open(输出文件,"ab") as f_rst:
    for line in all_lines_set:
        f_rst.write(line + 换行符)
#-- 打点()
#-- print(f"\n写入完毕,耗时:{计时()}")
print(f"\n输出文件:{输出文件}")

#-- 打点()
#-- print(f"\n\n总耗时:{计时(0)}")
print("———— 结束 ————")

附:

(2)用正则表达式来分行

import re

# (2)正则分行 二进制的话要加b, b''' '''
regx = '''[\w\~`\!\@\#\$\%\^\&\*\(\)\_\-\+\=\[\]\{\}\:\;\,\.\/\<\>\?]+'''
lines = re.findall(regx, data)

2. 按md5比较

import hashlib
import os
#-- from u_工具 import *
print("———— 开始 ————")
#-- 打点()

# 用来配置的变量
输入目录 = "./a_输入"
输出目录 = "./b_输出"
输出文件 = f"{输出目录}/去重结果.txt"

# 预处理
# 目录不存在就手动建立
if not os.path.exists(输出目录):
    os.makedirs(输出目录)
if not os.path.exists(输入目录):
    os.makedirs(输入目录)
#-- 输出文件 = 文件名防重_追加数字(输出文件)

# 获取待去重文件
待去重文件列表 = [f"{输入目录}/{i}" for i in os.listdir(输入目录)]
#-- 待去重文件列表 = []
#-- getDeepFilePaths(待去重文件列表,输入目录,"txt")
print(f"\n总共{len(待去重文件列表)}个文件")

def gen_md5(data):
    md5 = hashlib.md5()
    if repr(type(data)) == "<class 'str'>":
        data = data.encode('utf-8')
    md5.update(data)
    return md5.hexdigest()

# 实际处理
md5集 = set()
with open(输出文件, "a") as f_rst:
    文件个数 = 0
    for 文件 in 待去重文件列表:
        文件个数 += 1
        print(f"\n处理第{文件个数}个文件")

        # 计算总行数
        with open(文件, 'rb') as f:
            行数 = 0
            buf_size = 1024 * 1024
            buf = f.read(buf_size)
            while buf:
                行数 += buf.count(b'\n')
                buf = f.read(buf_size)

        # 读取、分行、去重、写入
        #-- 打点()
        i = 0
        for line_带换行 in open(文件):
            i += 1
            line = line_带换行.strip()
            md5值 = gen_md5(line)
            if md5值 not in md5集:
                md5集.add(md5值)
                f_rst.write(line_带换行)

            百分比 = i / 行数 * 10
            if 百分比 == int(百分比):
                print(f"已完成{int(百分比)*10}%")
                #-- 打点()
                #-- print(f"耗时:{计时()}")

print(f"\n输出文件:{输出文件}")

#-- 打点()
#-- print(f"\n\n总耗时:{计时(0)}")
print("———— 结束 ————")

三、二路归并

import hashlib
import os
import platform
import queue
import shutil
from uuid import uuid1
from u_工具 import *

print("———— 开始 ————")
打点()

# 1.用来配置的变量
输入目录 = "./a_输入"
输出目录 = "./b_输出"
输出文件 = f"{输出目录}/去重结果.txt"
临时目录 = "./c_临时"
小文件大小 = 50 * 1024 * 1024  # 50M

# 2.预处理
# 目录不存在就手动建立
if not os.path.exists(输出目录):
    os.makedirs(输出目录)
if not os.path.exists(输入目录):
    os.makedirs(输入目录)
if not os.path.exists(临时目录):
    os.makedirs(临时目录)
shutil.rmtree(临时目录)
os.makedirs(临时目录)
输出文件 = 文件名防重_追加数字(输出文件)

# 获取待去重文件
# 待去重文件列表 = [f"{输入目录}/{i}" for i in os.listdir(输入目录)]
待去重文件列表 = []
getDeepFilePaths(待去重文件列表,输入目录,"txt")
print(f"总共{len(待去重文件列表)}个文件")

换行符 = b"\n"
if platform.system().lower() == 'windows':
    换行符 = b"\r\n"

# 3.实际处理

# (1)分割大文件
打点()
待排序文件列表 = []
待补全数据 = b""
for 文件 in 待去重文件列表:
    with open(文件, 'rb') as f:
        buf = f.read(小文件大小)
        while buf:
            data = buf.split(换行符,1)
            新路径 = f"{临时目录}/无序_{序号(1)}_{uuid1()}.txt"
            with open(新路径, 'ab') as ff:
                ff.write(待补全数据 + data[0])
            待排序文件列表.append(新路径)
            try:
                待补全数据 = data[1]
            except:
                待补全数据 = b""
            buf = f.read(小文件大小)
    新路径 = f"{临时目录}/无序_{序号(1)}_{uuid1()}.txt"
    with open(新路径, 'ab') as ff:
            ff.write(待补全数据 + 换行符)
            待排序文件列表.append(新路径)
    待补全数据 = b""
del buf,data,待补全数据
打点()
print(f"\n分割大文件完成,共耗时:{计时()}")

# (2)排序小文件
打点()
序号_重置(1)
待归并文件队列 = queue.Queue()
for 文件 in 待排序文件列表:
    with open(文件, "rb") as f:
        data = f.read()
    data = set(data.split(换行符))
    if b"" in data:
        data.remove(b"")
    if 换行符 in data:
        data.remove(换行符)
    data = sorted(data)

    新路径 = f"{临时目录}/有序_{序号(1)}_{uuid1()}.txt"
    with open(新路径, 'ab') as ff:
        for line in data:
            ff.write(line + 换行符)
    待归并文件队列.put(新路径)
    os.remove(文件)
del data
打点()
print(f"\n排序小文件完成,共耗时:{计时()}")

# (3)归并小文件
打点("归并前")
序号_重置(1)
个数 = 待归并文件队列.qsize()
归并次数 = 个数 - 1
print(f"\n\n归并共{归并次数}次")
当前次数 = 0
while 个数 > 1:
    当前次数 += 1
    print(f"\n执行第{当前次数}次归并")
    文件路径a = 待归并文件队列.get()
    文件路径b = 待归并文件队列.get()
    新文件路径 = f"{临时目录}/{序号(1)}_{uuid1()}.txt"
    if 当前次数 == 归并次数:
        新文件路径 = 输出文件
    with open(文件路径a,"rb") as 文件a, open(文件路径b,"rb") as 文件b, open(新文件路径,"wb") as ff:
        # region 归并操作
        is_a_over = False
        is_b_over = False

        a = 文件a.readline().strip()
        b = 文件b.readline().strip()
        last = None

        while not (is_a_over and is_b_over):

            if is_a_over:
                b = 文件b.readline()
                if not b:
                    is_b_over = True
                else:
                    ff.write(b)

            elif is_b_over:
                a = 文件a.readline()
                if not a:
                    is_a_over = True
                else:
                    ff.write(a)

            else:
                # region 处理初始赋值
                if not a:
                    is_a_over = True
                    if not b:
                        is_b_over = True
                        continue
                    else:
                        ff.write(b + 换行符)
                        continue

                if not b:
                    is_b_over = True
                    ff.write(a + 换行符)
                    continue
                # endregion

                if a <= b:
                    if a == b or a == last:
                        a = 文件a.readline().strip()
                        if not a:
                            is_a_over = True
                            ff.write(b + 换行符)
                        continue
                    else:
                        last = a
                        ff.write(last + 换行符)
                        a = 文件a.readline().strip()
                        if not a:
                            is_a_over = True
                            ff.write(b + 换行符)
                        continue
                else:
                    if b == last:
                        b = 文件b.readline().strip()
                        if not b:
                            is_b_over = True
                            ff.write(a + 换行符)
                        continue
                    else:
                        last = b
                        ff.write(last + 换行符)
                        b = 文件b.readline().strip()
                        if not b:
                            is_b_over = True
                            ff.write(a + 换行符)
                        continue
        # endregion

    待归并文件队列.put(新文件路径)
    os.remove(文件路径a)
    os.remove(文件路径b)
    个数 = 待归并文件队列.qsize()
    打点()
    print(f"耗时:{计时()}")

打点("归并后")
print(f"\n\n归并小文件完成,共耗时:{计时('归并前','归并后')}")
print(f"\n输出文件:{输出文件}")

打点()
print(f"\n\n总耗时:{计时(0)}")
print("———— 结束 ————")

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Python实现对文件进行单词划分并去重排序操作示例

    本文实例讲述了Python实现对文件进行单词划分并去重排序操作.分享给大家供大家参考,具体如下: 文件名:test1.txt 文件内容: But soft what light through yonder window breaks It is the east and Juliet is the sun Arise fair sun and kill the envious moon Who is already sick and pale with grief 样例输出: Enter fi

  • Python实现的删除重复文件或图片功能示例【去重】

    本文实例讲述了Python实现的删除重复文件或图片功能.分享给大家供大家参考,具体如下: 通过python爬虫或其他方式保存的图片文件通常包含一些重复的图片或文件, 通过下面的python代码可以将重复的文件删除以达到去重的目的.其中,文件目录结构如下图: # /usr/bin/env python # -*- coding:utf-8 -*- # 运行的代码文件要放到删除重复的文件或图片所包含的目录中 import os import hashlib def filecount(): file

  • Python实现的txt文件去重功能示例

    本文实例讲述了Python实现的txt文件去重功能.分享给大家供大家参考,具体如下: # -*- coding:utf-8 -*- #! python2 import shutil a=0 readDir = "/Users/Administrator/Desktop/old.txt" #old writeDir = "/Users/Administrator/Desktop/new.txt" #new # txtDir = "/home/Administ

  • Python统计文件中去重后uuid个数的方法

    本文实例讲述了Python统计文件中去重后uuid个数的方法.分享给大家供大家参考.具体如下: 利用正则表达式按行获取日志文件中的的uuid,并且统计这些uuid的去重个数(去重利用set) import re pattern=re.compile(r'&uuid=.*&') uuidset=set() with open('request.log.2015-05-26','rt') as f: for line in f: all=pattern.findall(line) if len

  • python 高效去重复 支持GB级别大文件的示例代码

    如下所示: #coding=utf-8 import sys, re, os def getDictList(dict): regx = '''[\w\~`\!\@\#\$\%\^\&\*\(\)\_\-\+\=\[\]\{\}\:\;\,\.\/\<\>\?]+''' with open(dict) as f: data = f.read() return re.findall(regx, data) def rmdp(dictList): return list(set(dictL

  • python批量查询、汉字去重处理CSV文件

    CSV文件用记事本打开后一般为由逗号隔开的字符串,其处理方法用Python的代码如下.为方便各种程度的人阅读在代码中有非常详细的注释. 1.查询指定列,并保存到新的csv文件. # -*- coding: utf-8 -*- ''''' Author: Good_Night Time: 2018/1/30 03:50 Edition: 1.0 ''' # 导入必须的csv库 import csv # 创建临时文件temp.csv找出所需要的列 temp_file = open("temp.csv

  • 对python读写文件去重、RE、set的使用详解

    如下所示: # -*- coding:utf-8 -*- from datetime import datetime import re def Main(): sourcr_dir = '/data/u_lx_data/fudan/muying/muying_11yue_all.txt' target_dir = '/data/u_lx_data/fudan/muying/python/uid_regular_get.txt' uset = set() #去重 print("开始.....&q

  • 用python删除文件夹中的重复图片(图片去重)

    第一部分:判断两张图片是否相同 要查找重复的图片,必然绕不开判断两张图片是否相同.判断两张图片简单呀!图片可以看成数组,比较两个数组是否相等不就行了.但是这样做太过简单粗暴,因为两个数组的每个元素都要一一比较,效率很低.为了尽量避免两个庞大的数组比较: 先进行两张图片的大小(byte)比较,若大小不相同,则两张图片不相同: 在两张图片的大小相同的前提下,进行两张图片的尺寸(长和宽)比较,若尺寸不相同,则两张不相同: 在两张图片的尺寸相同的前提下,进行两张图片的内容(即数组元素)比较,若内容不相同

  • Python 如何实现文件自动去重

    Python 文件自动去重 平日里一来无聊,二来手巧,果然下载了好多无(luan)比(qi)珍(ba)贵(zao)的资料,搞得我小小的硬盘(已经扩到6T了)捉襟见肘, 有次无意间,发现有两个居然长得一毛一样,在房子这么小的情况下,我怎能忍两个一毛一样的东西不要脸皮的躺在我的硬盘里,果断搞掉一个,整理一下,本来想文件名一样的就保留一份,但问题出现了,居然有名字一样,内容却完全不一样的文件,想我背朝黄土面朝天吹着空调吃着西瓜下载下来的东西,删除是不可能的,这辈子都是不可能删除的.可是我也又不能把这数

  • Python实现的远程文件自动打包并下载功能示例

    本文实例讲述了Python实现的远程文件自动打包并下载功能.分享给大家供大家参考,具体如下: 一 点睛 在Linux系统集群运营当中,时常需要批量远程执行Linux命令,并且双向同步文件的操作. 本示例通过使用spawn()方法执行ssh.scp 命令的思路来实现. 二 代码 import pexpect import sys ip="192.168.0.104" user="root" passwd="123456" target_file=&

  • Python实现FTP文件定时自动下载的步骤

    之前遇到技术问题总能在技术博客上得到启发,十分感谢各位的无私分享.而自己却很少发文,固然是水平有限,但也限制了知识积累和总结.今后多总结分享,回馈博客的同时也希望大家多多批评. 一.需求: 某数据公司每日15:00~17:00之间,在其FTP发布当日数据供下载,我方需及时下载当日数据至指定本地目录. 二.分析: 1.需实现FTP登陆.查询.下载功能: 解答:使用内置的ftplib模块中FTP类: 2.需判断文件是否下载: 解答:使用os模块中path.exists方法: 3.需判断在指定时间段内

  • Pycharm创建python文件自动添加日期作者等信息(步骤详解)

    第一步 找到 Preferences,点击进入.进入后找到 Editor – File and Code Templates – Python Script . 第二步 添加自己所需要的信息 第三步 添加完成后,点击 OK 键进行保存. 新建python文件就会看到已添加的默认信息. 常用配置 #-- coding: utf-8 -- #@Time : ${DATE} ${TIME} #@Author : XXXX #@Email : XXXX@qq.com #@File : ${NAME}.p

  • Python中根据时间自动创建文件夹的代码实现

    导语 ​ 电脑桌面文件太多查找起来比较花费时间,并且凌乱的电脑桌面也会影响工作心情,于是利用python根据时间自动建立当日文件夹,这样就可以把桌面上文件按时间进行存放. 代码实现 # _*_coding:utf-8_*_ import os import datetime def create_folder(path): # 年-月-日 时:分:秒 now_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") # 年

  • Python如何根据字幕文件自动给视频添加字幕效果

    目录 功能描述: 字幕文件格式: 扩展库: 参考代码: 运行方式: 总结 功能描述: 根据给定的字幕文件中的字幕信息,自动给视频添加字幕,运行程序后输入要添加字幕的视频文件和对应的字幕文件路径即可.实际使用时不需要对程序做任何修改,只需要根据实际的视频内容来修改字幕文件就可以,自动把字幕文字添加到视频下方并居中显示. 字幕文件格式: 扩展库: pip install moviepy 1.0.0 pip install imageio pip install imageio-ffmpeg 另外,需

  • Python脚本实现一键自动整理办公文件

    目录 导语: 1.准备 2.原理 3.自定义整理 导语: 举例:Python做一个根据后缀名整理文件的工具,先来看看效果: 自动整理前: 自动整理后: 这样看起来就好很多了. 1.准备 开始之前,你要确保Python和pip已经成功安装在电脑上,如果没有,可以访问这篇文章:python Windows最新版本安装教程 我们只需要修改源代码主程序中调用 auto_organize函数的参数即可完成对对应文件夹的整理,比如我想整理  C:\Users\83493\Downloads 文件夹: if

  • 基于Python制作一个文件去重小工具

    目录 前言 实现步骤 补充 前言 常常在下载网络素材时有很多的重复文件乱七八糟的,于是想实现一个去重的操作. 主要实现思路就是遍历出某个文件夹包括其子文件夹下面的所有文件,最后,将所有文件通过MD5函数的对比筛选出来,最后将重复的文件移除. 实现步骤 用到的第三方库都比较的常见,其中只有hashlib是用来对比文件的不是很常见.其他的都是一些比较常见的第三方库用来做辅助操作. import os # 应用文件操作 import hashlib # 文件对比操作 import logging #

随机推荐