最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python重復(fù)文件批量整理工具的設(shè)計與實現(xiàn)

 更新時間:2025年02月09日 07:56:11   作者:黑客白澤  
這篇文章主要為大家詳細(xì)介紹了如何通關(guān)Python編寫一個重復(fù)文件批量整理工具,可以在文件夾內(nèi)對文件進(jìn)行去重和分類存儲,有需要的可以了解下

1. 簡介

這款文件整理工具主要用于在文件夾內(nèi)對文件進(jìn)行去重和分類存儲,尤其適用于處理圖片等文件類型。用戶可以通過選擇源目錄、目標(biāo)目錄、重復(fù)文件目錄以及非重復(fù)文件目錄,快速完成文件分類和去重工作。工具支持讀取 MD5 列表來識別重復(fù)文件,并根據(jù)文件的修改時間進(jìn)行分類存儲。此外,工具還支持多線程處理,避免界面卡頓,提升用戶體驗。

功能

1.目錄選擇和配置:

  • 支持設(shè)置基準(zhǔn)目錄、目標(biāo)目錄、重復(fù)文件目錄和非重復(fù)文件目錄。
  • 支持通過瀏覽按鈕快速選擇文件夾路徑。

2.文件去重和分類:

  • 使用 MD5 校驗碼對文件進(jìn)行去重,判斷文件是否重復(fù)。
  • 如果啟用了 MD5 列表,工具會加載先前保存的 MD5 列表,以加速去重過程。
  • 根據(jù)文件的修改時間,自動將文件按年和月分類存儲。

3.多線程處理:

  • 采用多線程技術(shù),使得文件處理過程不阻塞主線程,確保界面保持響應(yīng)。
  • 文件的移動操作在后臺線程中進(jìn)行,避免影響 UI 界面的流暢性。

4.支持圖片文件類型:

  • 支持常見圖片格式,如 JPEG、PNG、BMP 和 HEIC。
  • 對 HEIC 文件進(jìn)行特殊處理,提取文件的 EXIF 時間戳,作為文件分類的依據(jù)。

5.日志記錄:

  • 提供實時日志記錄功能,記錄文件處理的詳細(xì)過程。
  • 支持日志批量更新,減少對 UI 的頻繁更新,提高性能。

6.MD5 列表管理:

可加載和保存 MD5 列表,記錄基準(zhǔn)文件的 MD5 值,幫助后續(xù)識別重復(fù)文件。

使用方法

配置目錄:

  • 啟動工具后,首先配置四個文件夾路徑:
  • 基準(zhǔn)目錄:包含待處理文件的源目錄。
  • 目標(biāo)目錄:包含待比對的目標(biāo)文件夾。
  • 重復(fù)文件目錄:存放重復(fù)文件的目錄。
  • 非重復(fù)文件目錄:存放未重復(fù)文件的目錄。

選擇選項:

  • 啟用“讀取 MD5 列表”選項來加載已保存的 MD5 列表。
  • 啟用“啟用分類存儲”選項將文件按年和月進(jìn)行分類存儲。

開始處理:

  • 點擊“開始處理”按鈕,工具會自動掃描源目錄和目標(biāo)目錄,識別重復(fù)文件并進(jìn)行分類存儲。
  • 處理過程中,工具會在日志框中顯示詳細(xì)的操作信息。

文件分類與去重:

  • 工具根據(jù)文件的 MD5 校驗碼判斷是否為重復(fù)文件,重復(fù)文件將移動到指定的“重復(fù)文件目錄”。
  • 未重復(fù)的文件將按其修改時間(年月)分類,存放到指定的“非重復(fù)文件目錄”中。

完成處理:

文件處理完成后,工具會在日志框中顯示相關(guān)信息,并自動保存更新的 MD5 列表到“非重復(fù)文件目錄”中。

2. 運行效果

3.相關(guān)源碼

import os
import hashlib
import shutil
import json
import threading
import re
import io
import exifread
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
from datetime import datetime
from PIL import Image
from PIL.ExifTags import TAGS
import pillow_heif
from pillow_heif import register_heif_opener

class FileOrganizerApp:
    def __init__(self, root):
        self.root = root
        self.root.title("文件整理工具")
         
        # 變量初始化
        self.base_dir = tk.StringVar()
        self.target_dir = tk.StringVar()
        self.duplicate_dir = tk.StringVar()
        self.unique_dir = tk.StringVar()
        self.enable_classify = tk.BooleanVar(value=True)
        self.enable_md5list = tk.BooleanVar(value=False)
        
        self.dictfile_name = "base_md5_list.txt"
        
        # 創(chuàng)建register_heif_opener模塊里的一個類然后再Image.open打開HEIC文件
        register_heif_opener()
        
        # 創(chuàng)建界面組件
        self.create_widgets()

    def create_widgets(self):
        # 目錄選擇部分
        dir_frame = ttk.LabelFrame(self.root, text="目錄配置")
        dir_frame.pack(padx=10, pady=5, fill=tk.X)
        
        self.create_dir_selector(dir_frame, "基準(zhǔn)目錄:", self.base_dir, 0)
        self.create_dir_selector(dir_frame, "目標(biāo)目錄:", self.target_dir, 1)
        self.create_dir_selector(dir_frame, "重復(fù)文件目錄:", self.duplicate_dir, 2)
        self.create_dir_selector(dir_frame, "非重復(fù)文件目錄:", self.unique_dir, 3)
        
        # 選項配置
        opt_frame = ttk.LabelFrame(self.root, text="選項配置")
        opt_frame.pack(padx=10, pady=5, fill=tk.X)
        
        ttk.Checkbutton(opt_frame, text="啟用分類存儲", variable=self.enable_classify).pack(anchor=tk.W)
        ttk.Checkbutton(opt_frame, text="讀取MD5列表", variable=self.enable_md5list).pack(anchor=tk.W)
        
        # 操作按鈕
        btn_frame = ttk.Frame(self.root)
        btn_frame.pack(padx=10, pady=5, fill=tk.X)
        ttk.Button(btn_frame, text="開始處理", command=self.start_processing).pack(side=tk.LEFT)
        
        # 日志顯示
        self.log_text = tk.Text(self.root, height=15)
        self.scrollbar = tk.Scrollbar(root, command=self.log_text.yview)  
        self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)  
        self.log_text.config(yscrollcommand=self.scrollbar.set)
        self.log_text.pack(padx=10, pady=5, fill=tk.BOTH, expand=True)

    def create_dir_selector(self, parent, label, var, row):
        frame = ttk.Frame(parent)
        frame.grid(row=row, column=0, sticky="ew", padx=5, pady=2)
        
        ttk.Label(frame, text=label).pack(side=tk.LEFT)
        entry = ttk.Entry(frame, textvariable=var, width=40)
        entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
        ttk.Button(frame, text="瀏覽...", command=lambda: self.select_directory(var)).pack(side=tk.LEFT)
    
    def select_directory(self, var):
        dir_path = filedialog.askdirectory()
        if dir_path:
            var.set(dir_path)
    
    def log(self, message):
        # 批量更新日志,減少頻繁刷新UI
        self.log_text.insert(tk.END, message + "\n")
        self.root.update_idletasks()
    
    def calculate_md5(self, filepath):
        hash_md5 = hashlib.md5()
        with open(filepath, "rb") as f:
            for chunk in iter(lambda: f.read(4096), b""):
                hash_md5.update(chunk)
        return hash_md5.hexdigest()
    
    def save_dict_to_file(self, dictionary, file_path):
        with open(file_path, 'w', encoding='utf-8') as file:
            json.dump(dictionary, file, ensure_ascii=False, indent=4)

    def load_dict_from_file(self, file_path):
        with open(file_path, 'r', encoding='utf-8') as file:
            return json.load(file)
    
    def get_unique_filename(self, dest_dir, filename):
        base, ext = os.path.splitext(filename)
        counter = 1
        new_name = filename
        while os.path.exists(os.path.join(dest_dir, new_name)):
            new_name = f"{base}_{counter}{ext}"
            counter += 1
        return new_name

    def is_image(self, file_path):
        ext = os.path.splitext(file_path)[1].lower()
        return ext in [".jpg", ".jpeg", ".png", ".bmp", ".heic"]

    def get_file_time(self, file_path):
        mtime = os.path.getmtime(file_path)
        ext = os.path.splitext(file_path)[1].lower()

        if self.is_image(file_path):
            if ext == ".heic":
                mtime = self.get_heic_original(file_path)
                mtime = self.replace_limited(mtime, ':', '-', 2)
                dt_object = datetime.strptime(mtime, "%Y-%m-%d %H:%M:%S")
                mtime = dt_object.timestamp()
            else:
                with open(file_path, 'rb') as f:
                    tags = exifread.process_file(f, details=False)
                    if 'EXIF DateTimeOriginal' in tags:
                        mtime = str(tags['EXIF DateTimeOriginal'])
                        mtime = self.replace_limited(mtime, ':', '-', 2)
                        dt_object = datetime.strptime(mtime, "%Y-%m-%d %H:%M:%S")
                        mtime = dt_object.timestamp()
        return mtime

    def process_files(self):
        base_files = {}
        
        if self.enable_md5list.get():
            base_md5_path = os.path.join(self.base_dir.get(), self.dictfile_name)
            if os.path.exists(base_md5_path):
                base_files = self.load_dict_from_file(base_md5_path)
                self.log(f"基準(zhǔn)MD5已加載: {base_md5_path}")
        else:
            for root, _, files in os.walk(self.base_dir.get()):
                for file in files:
                    path = os.path.join(root, file)
                    md5 = self.calculate_md5(path)
                    base_files[md5] = file
                    self.log(f"基準(zhǔn)文件已掃描: {path}")

        for root, _, files in os.walk(self.target_dir.get()):
            for file in files:
                src_path = os.path.join(root, file)
                md5 = self.calculate_md5(src_path)
                self.log(f"正在處理: {src_path}")
                
                if md5 in base_files:
                    dest_dir = self.duplicate_dir.get()
                    dest_path = os.path.join(dest_dir, self.get_unique_filename(dest_dir, file))
                    shutil.move(src_path, dest_path)
                    self.log(f"重復(fù)文件已移動: {dest_path}")
                else:
                    if self.enable_classify.get():
                        mtime = self.get_file_time(src_path)
                        date_dir_Y = datetime.fromtimestamp(mtime).strftime("%Y")
                        date_dir_m = datetime.fromtimestamp(mtime).strftime("%m")
                        dest_dir = os.path.join(self.unique_dir.get(), date_dir_Y, date_dir_m)
                    else:
                        dest_dir = self.unique_dir.get()
                    
                    os.makedirs(dest_dir, exist_ok=True)
                    dest_path = os.path.join(dest_dir, self.get_unique_filename(dest_dir, file))
                    shutil.move(src_path, dest_path)
                    self.log(f"非重復(fù)文件已移動: {dest_path}")

        dest_md5_path = os.path.join(self.unique_dir.get(), self.dictfile_name)
        self.save_dict_to_file(base_files, dest_md5_path)
        self.log(f"基準(zhǔn)MD5已輸出: {dest_md5_path}")

    def start_processing(self):
        try:
            dirs = [
                self.base_dir.get(),
                self.target_dir.get(),
                self.duplicate_dir.get(),
                self.unique_dir.get()
            ]
            
            for d in dirs:
                if not d:
                    raise ValueError("所有目錄都必須設(shè)置")
                os.makedirs(d, exist_ok=True)
            
            # 啟動新線程處理文件
            threading.Thread(target=self.process_files, daemon=True).start()
            messagebox.showinfo("完成", "文件處理已開始,請稍候!")
        except Exception as e:
            messagebox.showerror("錯誤", str(e))
            self.log(f"錯誤發(fā)生: {str(e)}")

if __name__ == "__main__":
    root = tk.Tk()
    app = FileOrganizerApp(root)
    root.mainloop()

4.總結(jié)

這款文件整理工具是一個高效且易于使用的文件去重和分類存儲工具。它結(jié)合了 MD5 校驗和文件時間戳分類,確保用戶能夠快速識別重復(fù)文件并將文件按時間進(jìn)行合理分類。工具采用了多線程技術(shù),有效避免了長時間操作導(dǎo)致的界面卡頓,提供了流暢的用戶體驗。通過日志記錄和 MD5 列表管理,用戶可以清晰地了解文件處理的每一步操作。此外,該工具支持多種常見的圖片格式,且對 HEIC 文件進(jìn)行了專門的處理,使其適應(yīng)了現(xiàn)代文件管理的需求。

以上就是Python重復(fù)文件批量整理工具的設(shè)計與實現(xiàn)的詳細(xì)內(nèi)容,更多關(guān)于Python整理重復(fù)文件的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 安裝python依賴包psycopg2來調(diào)用postgresql的操作

    安裝python依賴包psycopg2來調(diào)用postgresql的操作

    這篇文章主要介紹了安裝python依賴包psycopg2來調(diào)用postgresql的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01
  • 主流Python語音轉(zhuǎn)文字(STT)庫實戰(zhàn)指南

    主流Python語音轉(zhuǎn)文字(STT)庫實戰(zhàn)指南

    語音轉(zhuǎn)文字的核心是通過信號處理、特征提取和模式識別將聲波轉(zhuǎn)換為文本,下面這篇文章主要介紹了主流Python語音轉(zhuǎn)文字(STT)庫的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2026-01-01
  • Python中用pycurl監(jiān)控http響應(yīng)時間腳本分享

    Python中用pycurl監(jiān)控http響應(yīng)時間腳本分享

    這篇文章主要介紹了Python中用pycurl監(jiān)控http響應(yīng)時間腳本分享,本文腳本實現(xiàn)監(jiān)控http相應(yīng)碼,響應(yīng)大小,建立連接時間,準(zhǔn)備傳輸時間,傳輸?shù)谝粋€字節(jié)時間,完成時間,需要的朋友可以參考下
    2015-02-02
  • Python實現(xiàn)Window路徑格式轉(zhuǎn)換為Linux路徑格式的代碼

    Python實現(xiàn)Window路徑格式轉(zhuǎn)換為Linux路徑格式的代碼

    這篇文章主要介紹了Python實現(xiàn)Window路徑格式轉(zhuǎn)換為Linux路徑格式的方法,文中通過代碼示例講解的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-07-07
  • Python統(tǒng)計文件中去重后uuid個數(shù)的方法

    Python統(tǒng)計文件中去重后uuid個數(shù)的方法

    這篇文章主要介紹了Python統(tǒng)計文件中去重后uuid個數(shù)的方法,實例分析了Python正則匹配及字符串操作的相關(guān)技巧,需要的朋友可以參考下
    2015-07-07
  • python?包實現(xiàn)?time?時間管理操作

    python?包實現(xiàn)?time?時間管理操作

    這篇文章主要介紹了python包實現(xiàn)time時間管理操作,文章通過獲取當(dāng)前時間戳,即當(dāng)前系統(tǒng)內(nèi)表示時間的一個浮點數(shù),下文更多相關(guān)內(nèi)容需要的小伙伴可以參考一下
    2022-04-04
  • Python Pywavelet 小波閾值實例

    Python Pywavelet 小波閾值實例

    今天小編就為大家分享一篇Python Pywavelet 小波閾值實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-01-01
  • 關(guān)于PyQt5主窗口圖標(biāo)顯示問題匯總

    關(guān)于PyQt5主窗口圖標(biāo)顯示問題匯總

    這篇文章主要介紹了關(guān)于PyQt5主窗口圖標(biāo)顯示問題匯總,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-03-03
  • 常用python編程模板匯總

    常用python編程模板匯總

    這篇文章主要為大家詳細(xì)介紹了常用python編程模板,總結(jié)了Python編程常用模板,感興趣的朋友可以參考一下
    2016-02-02
  • 編寫自定義的Django模板加載器的簡單示例

    編寫自定義的Django模板加載器的簡單示例

    這篇文章主要介紹了編寫自定義的Django模板加載器的簡單示例,Django是各色人氣Python框架中最為著名的一個,需要的朋友可以參考下
    2015-07-07

最新評論

临清市| 通城县| 涟水县| 九台市| 房产| 东安县| 华坪县| 古蔺县| 安龙县| 翼城县| 晋江市| 宁波市| 治多县| 田林县| 临夏市| 巴中市| 米泉市| 随州市| 西平县| 双牌县| 石泉县| 启东市| 鸡泽县| 临海市| 绵阳市| 霸州市| 兴安盟| 昭通市| 罗定市| 洛阳市| 永宁县| 黄平县| 庄河市| 麻阳| 台山市| 界首市| 定结县| 普陀区| 紫阳县| 赣榆县| 桂阳县|