亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

1. 簡介

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

功能

1.目錄選擇和配置:

  • 支持設置基準目錄、目標目錄、重復文件目錄和非重復文件目錄。
  • 支持通過瀏覽按鈕快速選擇文件夾路徑。

2.文件去重和分類:

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

3.多線程處理:

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

4.支持圖片文件類型:

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

5.日志記錄:

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

6.MD5 列表管理:

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

使用方法

配置目錄:

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

選擇選項:

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

開始處理:

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

文件分類與去重:

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

完成處理:

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

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, "基準目錄:", self.base_dir, 0)
        self.create_dir_selector(dir_frame, "目標目錄:", self.target_dir, 1)
        self.create_dir_selector(dir_frame, "重復文件目錄:", self.duplicate_dir, 2)
        self.create_dir_selector(dir_frame, "非重復文件目錄:", 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"基準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"基準文件已掃描: {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"重復文件已移動: {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"非重復文件已移動: {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"基準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("所有目錄都必須設置")
                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 校驗和文件時間戳分類,確保用戶能夠快速識別重復文件并將文件按時間進行合理分類。工具采用了多線程技術(shù),有效避免了長時間操作導致的界面卡頓,提供了流暢的用戶體驗。通過日志記錄和 MD5 列表管理,用戶可以清晰地了解文件處理的每一步操作。此外,該工具支持多種常見的圖片格式,且對 HEIC 文件進行了專門的處理,使其適應了現(xiàn)代文件管理的需求。

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

相關(guān)文章

最新評論