[Python] 纯文本查看 复制代码
import os
import tkinter as tk
from tkinter import filedialog, messagebox, ttk
from datetime import datetime
import hashlib
import math
import re
class FileVerifier:
def __init__(self, master):
self.master = master
master.title("文件校验")
self.folder_path = tk.StringVar()
self.filter_rule = tk.StringVar()
self.create_widgets()
self.tree = self.create_treeview()
self.context_menu = self.create_context_menu()
self.file_paths = {}
def create_widgets(self):
# 使用Frame来组织并集中管理其他所有Widget
self.main_frame = tk.Frame(self.master)
self.main_frame.pack(fill=tk.BOTH, expand=True)
tk.Label(self.main_frame, text="文件夹路径:").grid(row=0, column=0, sticky="w")
# 增加sticky参数以确保控件填满单元格并左对齐
tk.Entry(self.main_frame, textvariable=self.folder_path).grid(row=0, column=1, sticky="we")
tk.Button(self.main_frame, text="浏览", command=self.select_folder).grid(row=0, column=2, sticky="e")
tk.Label(self.main_frame, text="文件名匹配规则:").grid(row=1, column=0, sticky="w")
tk.Entry(self.main_frame, textvariable=self.filter_rule).grid(row=1, column=1, sticky="we")
tk.Button(self.main_frame, text="开始校验", command=self.verify_files).grid(row=1, column=2, sticky="e")
def create_treeview(self):
columns = ('status', 'filename', 'size', 'modified', 'md5', 'path')
tree = ttk.Treeview(self.master, columns=columns, show='headings')
scrollbar = ttk.Scrollbar(self.master, orient=tk.VERTICAL, command=tree.yview)
tree.configure(yscrollcommand=scrollbar.set)
for col in columns:
tree.heading(col, text=col.capitalize())
tree.column(col, width=100)
tree.pack(fill=tk.BOTH, expand=True)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
return tree
def create_context_menu(self):
context_menu = tk.Menu(self.master, tearoff=0)
context_menu.add_command(label="打开文件", command=self.open_file)
context_menu.add_command(label="在 Windows 资源管理器中打开", command=self.open_file_in_explorer)
return context_menu
def select_folder(self):
folder_selected = filedialog.askdirectory()
if folder_selected:
self.folder_path.set(folder_selected)
def show_context_menu(self, event):
# 获取选中的项
iid = self.tree.identify_row(event.y)
if iid:
self.tree.selection_set(iid)
self.context_menu.post(event.x_root, event.y_root)
def open_file(self):
selected_item = self.tree.selection()
if selected_item:
file_path = self.file_paths[selected_item[0]]
if os.path.isfile(file_path):
os.startfile(file_path)
def open_file_in_explorer(self):
selected_item = self.tree.selection()
if selected_item:
file_path = self.file_paths[selected_item[0]]
file_dir = os.path.dirname(file_path)
os.startfile(file_dir)
def get_file_size(self, size):
if size >= 1024 * 1024:
return f"{size / (1024 * 1024):.2f} MB"
elif size >= 1024:
return f"{size / 1024:.2f} KB"
else:
return f"{size} B"
def calculate_md5(self, filename):
hash_md5 = hashlib.md5()
with open(filename, "rb") as f:
for chunk in iter(lambda: f.read(4096), b""):
hash_md5.update(chunk)
return hash_md5.hexdigest()
def verify_files(self):
folder_path = self.folder_path.get()
filter_rule = self.filter_rule.get()
if not folder_path:
messagebox.showerror("错误", "请选择文件夹路径!")
return
if not filter_rule:
messagebox.showerror("错误", "请输入文件名匹配规则!")
return
file_count = 0
self.tree.delete(*self.tree.get_children()) # 清空Treeview
self.file_paths.clear() # 清空文件路径字典
for root, dirs, files in os.walk(folder_path):
for name in files:
if filter_rule in name:
file_path = os.path.join(root, name)
file_size = os.path.getsize(file_path)
file_size_str = self.get_file_size(file_size)
modification_time = os.path.getmtime(file_path)
formatted_modification_time = datetime.fromtimestamp(modification_time).strftime('%Y-%m-%d %H:%M:%S')
md5 = self.calculate_md5(file_path)
status = "Ok" if file_size >= 10 * 1024 else "异常文件"
self.tree.insert('', tk.END, values=(status, name, file_size_str, formatted_modification_time, md5, file_path))
self.file_paths[self.tree.get_children()[-1]] = file_path
file_count += 1
self.master.update_idletasks()
self.master.minsize(self.tree.winfo_width(), self.tree.winfo_height())
messagebox.showinfo("完成", f"校验完成。共找到 {file_count} 个文件。")
self.check_file_date_continuity(files)
def check_file_date_continuity(self, file_list):
date_list = []
missing_dates = []
for file_name in file_list:
match = re.search(r'\d{8}', file_name)
if match:
date_str = match.group()
date = datetime.strptime(date_str, '%Y%m%d')
date_list.append(date)
date_list.sort()
for i in range(len(date_list) - 1):
if (date_list[i + 1] - date_list[i]).days > 1:
missing_dates.append(date_list[i + 1])
if missing_dates:
message = "以下日期的文件缺失:\n"
for date in missing_dates:
message += f"{date.strftime('%Y-%m-%d')}\n"
messagebox.showwarning("警告", message)
else:
messagebox.showinfo("通知", "文件名日期连续,没有缺失。")
if __name__ == "__main__":
root = tk.Tk()
app = FileVerifier(root)
root.mainloop()