1、轻松快速实现文件搜索
2、实现代码所在文件路径
3、对文件夹进行内容监测,可以监测文件新增减少甚至代码的新增减少

程序下载
通过网盘分享的文件:cursor+python开发文件监控与文件代码搜索工具.rar
链接: https://pan.baidu.com/s/1ty-DLJcgm6L1PWZev7MsRw?pwd=atds 提取码: atds

conda库下载
通过网盘分享的文件:condacu.yaml
链接: https://pan.baidu.com/s/1EpAikk4PcutqLy-6OkV1Eg?pwd=pruq 提取码: pruq

更多实用程序模拟器过检测相关和cursor最新版白嫖教学

cursor+python开发文件监控与文件代码搜索工具

file_diff_gui.py

import tkinter as tk
from tkinter import ttk, scrolledtext, filedialog, messagebox
import threading
import queue
from file_diff_checker import FolderDiffChecker
import time
import os
import re
from PIL import Image, ImageTk
import sys

class FileDiffGUI:
    def __init__(self, root):
        self.root = root
        self.root.title("文件监控与搜索工具")
        self.root.geometry("1000x800")
        
        # 显示广告
        self.show_ad()
        
        # 创建标签页
        self.notebook = ttk.Notebook(self.root)
        self.notebook.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # 创建三个标签页
        self.monitor_frame = ttk.Frame(self.notebook)
        self.code_search_frame = ttk.Frame(self.notebook)
        self.file_search_frame = ttk.Frame(self.notebook)
        
        # 添加标签页
        self.notebook.add(self.monitor_frame, text="文件监控")
        self.notebook.add(self.code_search_frame, text="代码搜索")
        self.notebook.add(self.file_search_frame, text="文件搜索")
        
        # 初始化各页面
        self.setup_monitor_page()
        self.setup_code_search_page()
        self.setup_file_search_page()
        
        # 状态栏
        self.status_var = tk.StringVar(value="就绪")
        self.status_bar = ttk.Label(self.root, textvariable=self.status_var, relief=tk.SUNKEN)
        self.status_bar.pack(side=tk.BOTTOM, fill=tk.X)

    def show_ad(self):
        """显示广告窗口"""
        try:
            # 创建广告窗口
            ad_window = tk.Toplevel(self.root)
            ad_window.title("软件说明")
            
            # 获取图片路径
            if getattr(sys, 'frozen', False):
                # 如果是打包后的exe
                base_path = os.path.dirname(sys.executable)
            else:
                # 如果是直接运行的py文件
                base_path = os.path.abspath(os.path.dirname(__file__))
            
            image_path = os.path.join(base_path, "xc201905.jpg")
            print(f"尝试加载图片: {image_path}")  # 添加调试信息
            
            if not os.path.exists(image_path):
                print(f"图片文件不存在: {image_path}")
                messagebox.showerror("错误", "找不到图片文件")
                return
            
            # 加载并显示图片
            image = Image.open(image_path)
            # 调整图片大小
            image = image.resize((300, 300), Image.Resampling.LANCZOS)
            photo = ImageTk.PhotoImage(image)
            
            # 创建标签显示图片
            label = tk.Label(ad_window, image=photo)
            label.image = photo  # 保持引用
            label.pack(padx=10, pady=10)
            
            # 添加说明文本
            text = tk.Label(ad_window, text="欢迎使用文件监控与搜索工具\n扫描二维码了解更多", 
                          font=("Arial", 12))
            text.pack(pady=10)
            
            # 添加关闭按钮
            close_btn = ttk.Button(ad_window, text="关闭", 
                                 command=ad_window.destroy)
            close_btn.pack(pady=10)
            
            # 设置窗口位置为居中
            ad_window.transient(self.root)
            ad_window.grab_set()
            
            # 计算窗口位置
            window_width = 320
            window_height = 400
            screen_width = self.root.winfo_screenwidth()
            screen_height = self.root.winfo_screenheight()
            x = (screen_width - window_width) // 2
            y = (screen_height - window_height) // 2
            ad_window.geometry(f"{window_width}x{window_height}+{x}+{y}")
            
        except Exception as e:
            print(f"显示广告时出错: {str(e)}")
            messagebox.showerror("错误", f"显示广告时出错: {str(e)}")

    def setup_file_search_page(self):
        """设置文件搜索页面"""
        # 顶部控制区域
        control_frame = ttk.LabelFrame(self.file_search_frame, text="搜索控制")
        control_frame.pack(fill=tk.X, padx=5, pady=5)
        
        # 文件夹选择
        path_label = ttk.Label(control_frame, text="搜索文件夹:")
        path_label.pack(side=tk.LEFT, padx=5)
        
        self.file_search_path_var = tk.StringVar()
        path_entry = ttk.Entry(control_frame, textvariable=self.file_search_path_var, width=50)
        path_entry.pack(side=tk.LEFT, padx=5)
        
        browse_btn = ttk.Button(control_frame, text="浏览", 
                               command=lambda: self.browse_folder(self.file_search_path_var))
        browse_btn.pack(side=tk.LEFT, padx=5)
        
        # 搜索选项区域
        search_options = ttk.Frame(self.file_search_frame)
        search_options.pack(fill=tk.X, padx=5, pady=5)
        
        # 搜索输入框
        self.file_name_var = tk.StringVar()
        name_label = ttk.Label(search_options, text="文件名:")
        name_label.pack(side=tk.LEFT, padx=5)
        
        name_entry = ttk.Entry(search_options, textvariable=self.file_name_var, width=40)
        name_entry.pack(side=tk.LEFT, padx=5)
        
        # 搜索选项
        self.exact_match_var = tk.BooleanVar(value=False)
        exact_check = ttk.Checkbutton(search_options, text="精确匹配", 
                                     variable=self.exact_match_var)
        exact_check.pack(side=tk.LEFT, padx=5)
        
        # 搜索按钮
        search_btn = ttk.Button(search_options, text="搜索", command=self.search_files)
        search_btn.pack(side=tk.LEFT, padx=5)
        
        # 结果显示区域
        result_frame = ttk.LabelFrame(self.file_search_frame, text="搜索结果")
        result_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # 文件列表
        self.file_list_tree = ttk.Treeview(result_frame, 
                                          columns=("name", "path", "size", "modified"),
                                          show="headings")
        
        # 设置列
        self.file_list_tree.heading("name", text="文件名")
        self.file_list_tree.heading("path", text="路径")
        self.file_list_tree.heading("size", text="大小")
        self.file_list_tree.heading("modified", text="修改时间")
        
        # 设置列宽
        self.file_list_tree.column("name", width=150)
        self.file_list_tree.column("path", width=400)
        self.file_list_tree.column("size", width=100)
        self.file_list_tree.column("modified", width=150)
        
        # 添加滚动条
        scrollbar = ttk.Scrollbar(result_frame, orient=tk.VERTICAL, 
                                command=self.file_list_tree.yview)
        self.file_list_tree.configure(yscrollcommand=scrollbar.set)
        
        # 布局
        self.file_list_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 按钮区域
        button_frame = ttk.Frame(result_frame)
        button_frame.pack(fill=tk.X, padx=5, pady=5)
        
        copy_selected_btn = ttk.Button(button_frame, text="复制选中路径",
                                     command=lambda: self.copy_path(self.file_list_tree))
        copy_selected_btn.pack(side=tk.LEFT, padx=2, expand=True, fill=tk.X)
        
        copy_all_btn = ttk.Button(button_frame, text="复制所有路径",
                                 command=lambda: self.copy_all_paths(self.file_list_tree))
        copy_all_btn.pack(side=tk.LEFT, padx=2, expand=True, fill=tk.X)

    def search_files(self):
        """执行文件搜索"""
        search_path = self.file_search_path_var.get()
        if not search_path:
            messagebox.showerror("错误", "请选择要搜索的文件夹!")
            return
            
        search_text = self.file_name_var.get()
        if not search_text:
            messagebox.showerror("错误", "请输入要搜索的文件名!")
            return
            
        # 清空现有结果
        self.file_list_tree.delete(*self.file_list_tree.get_children())
        self.status_var.set("正在搜索文件...")
        
        # 在新线程中执行搜索
        threading.Thread(target=self._file_search_task, daemon=True).start()

    def _file_search_task(self):
        """文件搜索任务"""
        try:
            search_path = self.file_search_path_var.get()
            search_text = self.file_name_var.get().lower()
            exact_match = self.exact_match_var.get()
            
            found_files = []
            total_checked = 0
            
            for root, _, files in os.walk(search_path):
                for file in files:
                    total_checked += 1
                    if total_checked % 100 == 0:  # 每检查100个文件更新一次状态
                        self.status_var.set(f"已检查 {total_checked} 个文件...")
                    
                    file_lower = file.lower()
                    if exact_match:
                        if file_lower == search_text:
                            self._add_file_to_results(root, file)
                    else:
                        if search_text in file_lower:
                            self._add_file_to_results(root, file)
            
            self.status_var.set(f"搜索完成,共检查 {total_checked} 个文件")
            messagebox.showinfo("完成", "文件搜索已完成!")
            
        except Exception as e:
            self.status_var.set("搜索出错")
            messagebox.showerror("错误", f"搜索过程中出错: {str(e)}")

    def _add_file_to_results(self, root, filename):
        """添加文件到结果列表"""
        try:
            full_path = os.path.join(root, filename)
            file_stat = os.stat(full_path)
            size = self._format_size(file_stat.st_size)
            modified = time.strftime('%Y-%m-%d %H:%M:%S', 
                                   time.localtime(file_stat.st_mtime))
            
            self.root.after(0, lambda: self.file_list_tree.insert('', 'end', values=(
                filename, full_path, size, modified
            )))
        except Exception as e:
            print(f"Error adding file to results: {e}")

    @staticmethod
    def _format_size(size):
        """格式化文件大小"""
        for unit in ['B', 'KB', 'MB', 'GB', 'TB']:
            if size < 1024.0:
                return f"{size:.2f} {unit}"
            size /= 1024.0
        return f"{size:.2f} PB"

    def browse_folder(self, path_var):
        """通用的文件夹选择方法"""
        folder_path = filedialog.askdirectory()
        if folder_path:
            path_var.set(folder_path)

    def setup_monitor_page(self):
        """设置文件监控页面"""
        # 顶部控制区域
        control_frame = ttk.LabelFrame(self.monitor_frame, text="监控控制")
        control_frame.pack(fill=tk.X, padx=5, pady=5)
        
        # 文件夹选择
        path_label = ttk.Label(control_frame, text="监控文件夹:")
        path_label.pack(side=tk.LEFT, padx=5)
        
        self.monitor_path_var = tk.StringVar()
        path_entry = ttk.Entry(control_frame, textvariable=self.monitor_path_var, width=50)
        path_entry.pack(side=tk.LEFT, padx=5)
        
        browse_btn = ttk.Button(control_frame, text="浏览", 
                               command=lambda: self.browse_folder(self.monitor_path_var))
        browse_btn.pack(side=tk.LEFT, padx=5)
        
        # 监控控制
        self.start_btn = ttk.Button(control_frame, text="开始监控", 
                                   command=self.toggle_monitoring)
        self.start_btn.pack(side=tk.LEFT, padx=5)
        
        # 间隔设置
        interval_label = ttk.Label(control_frame, text="检查间隔(秒):")
        interval_label.pack(side=tk.LEFT, padx=5)
        
        self.interval_var = tk.StringVar(value="5")
        interval_entry = ttk.Entry(control_frame, textvariable=self.interval_var, width=5)
        interval_entry.pack(side=tk.LEFT, padx=5)
        
        # 日志区域
        log_frame = ttk.LabelFrame(self.monitor_frame, text="变化日志")
        log_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        self.log_text = scrolledtext.ScrolledText(log_frame, wrap=tk.WORD, width=80, height=30)
        self.log_text.pack(fill=tk.BOTH, expand=True)
        
        # 初始化监控状态
        self.is_monitoring = False
        self.monitor_thread = None
        self.queue = queue.Queue()

    def setup_code_search_page(self):
        """设置代码搜索页面"""
        # 顶部控制区域
        control_frame = ttk.LabelFrame(self.code_search_frame, text="搜索控制")
        control_frame.pack(fill=tk.X, padx=5, pady=5)
        
        # 文件夹选择
        path_label = ttk.Label(control_frame, text="搜索文件夹:")
        path_label.pack(side=tk.LEFT, padx=5)
        
        self.code_search_path_var = tk.StringVar()
        path_entry = ttk.Entry(control_frame, textvariable=self.code_search_path_var, width=50)
        path_entry.pack(side=tk.LEFT, padx=5)
        
        browse_btn = ttk.Button(control_frame, text="浏览", 
                               command=lambda: self.browse_folder(self.code_search_path_var))
        browse_btn.pack(side=tk.LEFT, padx=5)
        
        # 搜索选项区域
        search_options = ttk.Frame(self.code_search_frame)
        search_options.pack(fill=tk.X, padx=5, pady=5)
        
        # 搜索输入框
        self.code_search_var = tk.StringVar()
        search_label = ttk.Label(search_options, text="搜索内容:")
        search_label.pack(side=tk.LEFT, padx=5)
        
        search_entry = ttk.Entry(search_options, textvariable=self.code_search_var, width=40)
        search_entry.pack(side=tk.LEFT, padx=5)
        
        # 搜索选项
        self.case_sensitive_var = tk.BooleanVar(value=False)
        case_check = ttk.Checkbutton(search_options, text="区分大小写", 
                                    variable=self.case_sensitive_var)
        case_check.pack(side=tk.LEFT, padx=5)
        
        self.regex_var = tk.BooleanVar(value=False)
        regex_check = ttk.Checkbutton(search_options, text="使用正则表达式", 
                                     variable=self.regex_var)
        regex_check.pack(side=tk.LEFT, padx=5)
        
        # 文件类型过滤
        filter_frame = ttk.Frame(self.code_search_frame)
        filter_frame.pack(fill=tk.X, padx=5, pady=5)
        
        filter_label = ttk.Label(filter_frame, text="文件类型:")
        filter_label.pack(side=tk.LEFT, padx=5)
        
        self.filter_var = tk.StringVar(value=".py .js .java .cpp .txt")
        filter_entry = ttk.Entry(filter_frame, textvariable=self.filter_var, width=30)
        filter_entry.pack(side=tk.LEFT, padx=5)
        
        # 搜索按钮
        search_btn = ttk.Button(filter_frame, text="搜索", command=self.search_code)
        search_btn.pack(side=tk.LEFT, padx=5)
        
        # 结果显示区域
        result_frame = ttk.LabelFrame(self.code_search_frame, text="搜索结果")
        result_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # 进度显示
        self.progress_text = scrolledtext.ScrolledText(result_frame, wrap=tk.WORD, 
                                                     width=80, height=5)
        self.progress_text.pack(fill=tk.X, padx=5, pady=5)
        
        # 文件列表
        self.files_tree = ttk.Treeview(result_frame, columns=("path", "matches"), 
                                      show="headings")
        self.files_tree.heading("path", text="文件路径")
        self.files_tree.heading("matches", text="匹配数")
        
        # 添加滚动条
        scrollbar = ttk.Scrollbar(result_frame, orient=tk.VERTICAL, 
                                 command=self.files_tree.yview)
        self.files_tree.configure(yscrollcommand=scrollbar.set)
        
        # 布局
        self.files_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 按钮区域
        button_frame = ttk.Frame(result_frame)
        button_frame.pack(fill=tk.X, padx=5, pady=5)
        
        copy_selected_btn = ttk.Button(button_frame, text="复制选中路径",
                                      command=lambda: self.copy_path(self.files_tree))
        copy_selected_btn.pack(side=tk.LEFT, padx=2, expand=True, fill=tk.X)
        
        copy_all_btn = ttk.Button(button_frame, text="复制所有路径",
                                  command=lambda: self.copy_all_paths(self.files_tree))
        copy_all_btn.pack(side=tk.LEFT, padx=2, expand=True, fill=tk.X)

    def copy_path(self, tree):
        """复制选中的文件路径"""
        selected = tree.selection()
        if not selected:
            messagebox.showinfo("提示", "请先选择要复制的文件")
            return
        
        try:
            # 根据不同的树形控件获取正确的路径列索引
            path_index = 1 if tree == self.file_list_tree else 0
            path = tree.item(selected[0])['values'][path_index]
            
            # 复制到剪贴板
            self.root.clipboard_clear()
            self.root.clipboard_append(path)
            self.root.update()  # 确保更新剪贴板
            
            # 更新状态栏
            self.status_var.set("已复制文件路径到剪贴板")
            
            # 显示成功提示
            messagebox.showinfo("成功", "文件路径已复制到剪贴板!")
        except Exception as e:
            messagebox.showerror("错误", f"复制失败: {str(e)}")

    def copy_all_paths(self, tree):
        """复制所有文件路径"""
        all_items = tree.get_children()
        if not all_items:
            messagebox.showinfo("提示", "没有可复制的文件路径")
            return
        
        try:
            paths = []
            # 根据不同的树形控件获取正确的路径列索引
            path_index = 1 if tree == self.file_list_tree else 0
            
            for item in all_items:
                path = tree.item(item)['values'][path_index]
                paths.append(path)
            
            all_paths = '\n'.join(paths)
            
            # 复制到剪贴板
            self.root.clipboard_clear()
            self.root.clipboard_append(all_paths)
            self.root.update()  # 确保更新剪贴板
            
            # 更新状态栏
            self.status_var.set(f"已复制全部 {len(paths)} 个文件路径到剪贴板")
            
            # 显示成功提示
            messagebox.showinfo("成功", f"已复制 {len(paths)} 个文件路径到剪贴板!")
        except Exception as e:
            messagebox.showerror("错误", f"复制失败: {str(e)}")

    def toggle_monitoring(self):
        """切换监控状态"""
        if not self.is_monitoring:
            if not self.monitor_path_var.get():
                messagebox.showerror("错误", "请选择要监控的文件夹!")
                return
            
            try:
                interval = int(self.interval_var.get())
                if interval < 1:
                    raise ValueError("间隔时间必须大于0")
            except ValueError:
                messagebox.showerror("错误", "请输入有效的检查间隔时间(秒)!")
                return
            
            self.start_monitoring()
        else:
            self.stop_monitoring()

    def start_monitoring(self):
        """开始监控"""
        self.is_monitoring = True
        self.start_btn.config(text="停止监控")
        self.status_var.set("正在监控文件夹变化...")
        
        # 创建监控器实例
        self.checker = FolderDiffChecker(self.monitor_path_var.get())
        
        # 在新线程中执行监控
        self.monitor_thread = threading.Thread(target=self._monitoring_task, daemon=True)
        self.monitor_thread.start()
        
        # 启动队列检查
        self.root.after(100, self.check_queue)

    def stop_monitoring(self):
        """停止监控"""
        self.is_monitoring = False
        self.start_btn.config(text="开始监控")
        self.status_var.set("监控已停止")
        self.log_text.insert(tk.END, "\n监控已停止\n")
        self.log_text.see(tk.END)

    def _monitoring_task(self):
        """监控任务"""
        try:
            while self.is_monitoring:
                differences = self.checker.check_differences()
                if differences:
                    report = self.checker.generate_report(differences)
                    self.queue.put(report)
                time.sleep(int(self.interval_var.get()))
        except Exception as e:
            self.queue.put(f"监控出错: {str(e)}\n")
            self.is_monitoring = False
            self.root.after(0, lambda: self.start_btn.config(text="开始监控"))

    def check_queue(self):
        """检查消息队列"""
        try:
            while True:
                message = self.queue.get_nowait()
                if isinstance(message, tuple):
                    msg_type, content = message
                    if msg_type == "error":
                        self.status_var.set("出错")
                        messagebox.showerror("错误", content)
                    elif msg_type == "result":
                        self.progress_text.insert(tk.END, content)
                        self.status_var.set("搜索完成")
                    elif msg_type == "complete":
                        messagebox.showinfo("完成", "搜索已完成!")
                    elif msg_type == "status":
                        self.status_var.set(content)
                        self.progress_text.insert(tk.END, f"{content}\n")
                    elif msg_type == "progress":
                        self.status_var.set(content)
                        self.progress_text.delete(1.0, tk.END)
                        self.progress_text.insert(tk.END, content)
                    if hasattr(self, 'progress_text'):
                        self.progress_text.see(tk.END)
                else:
                    # 处理监控报告
                    self.log_text.insert(tk.END, "\n" + message)
                    self.log_text.see(tk.END)
        except queue.Empty:
            pass
        
        if self.is_monitoring or getattr(self, '_searching', False):
            self.root.after(100, self.check_queue)

    def search_code(self):
        """执行代码搜索"""
        if not self.code_search_path_var.get():
            messagebox.showerror("错误", "请选择要搜索的文件夹!")
            return
        
        if not self.code_search_var.get():
            messagebox.showerror("错误", "请输入要搜索的内容!")
            return
        
        # 禁用搜索按钮,避免重复搜索
        self._searching = True
        
        # 清空之前的搜索结果
        self.progress_text.delete(1.0, tk.END)
        self.files_tree.delete(*self.files_tree.get_children())
        
        # 更新状态
        self.status_var.set("搜索中...请等待")
        self.progress_text.insert(tk.END, "开始搜索...\n")
        
        # 在新线程中执行搜索
        threading.Thread(target=self._code_search_task, daemon=True).start()
        
        # 启动队列检查
        if not self.is_monitoring:
            self.root.after(100, self.check_queue)

    def _code_search_task(self):
        """代码搜索任务"""
        try:
            search_text = self.code_search_var.get()
            folder_path = self.code_search_path_var.get()
            case_sensitive = self.case_sensitive_var.get()
            use_regex = self.regex_var.get()
            file_types = self.filter_var.get().split()
            
            if use_regex:
                try:
                    pattern = re.compile(search_text, 0 if case_sensitive else re.IGNORECASE)
                except re.error:
                    self.queue.put(("error", "无效的正则表达式!"))
                    return
            
            total_files = 0
            matches = 0
            file_match_counts = {}
            
            # 首先统计需要搜索的文件总数
            all_files = []
            for root, _, files in os.walk(folder_path):
                for file in files:
                    if any(file.endswith(ext) for ext in file_types):
                        all_files.append(os.path.join(root, file))
            
            total_to_search = len(all_files)
            self.queue.put(("status", f"找到 {total_to_search} 个文件需要搜索..."))
            
            # 显示进度的计数器
            for i, file_path in enumerate(all_files, 1):
                if i % 10 == 0:  # 每10个文件更新一次进度
                    progress = (i / total_to_search) * 100
                    self.queue.put(("progress", f"正在搜索... {progress:.1f}% ({i}/{total_to_search})"))
                
                try:
                    with open(file_path, 'r', encoding='utf-8') as f:
                        content = f.read()
                        match_count = 0
                        
                        if use_regex:
                            matches = len(list(pattern.finditer(content)))
                            if matches > 0:
                                match_count = matches
                        else:
                            if not case_sensitive:
                                content = content.lower()
                                search_text = search_text.lower()
                            match_count = content.count(search_text)
                        
                        if match_count > 0:
                            file_match_counts[file_path] = match_count
                            self.root.after(0, lambda p=file_path, c=match_count: 
                                self.files_tree.insert('', 'end', values=(p, c)))
                
                except Exception as e:
                    print(f"Error processing file {file_path}: {e}")
            
            # 更新最终结果
            summary = (f"搜索完成!\n"
                      f"检索了 {total_to_search} 个文件,"
                      f"在 {len(file_match_counts)} 个文件中找到 {sum(file_match_counts.values())} 处匹配。\n"
                      f"{'='*50}\n")
            self.queue.put(("result", summary))
            self.queue.put(("complete", "搜索完成"))
            
        except Exception as e:
            self.queue.put(("error", f"搜索过程中出错: {str(e)}"))
        finally:
            self._searching = False

def main():
    root = tk.Tk()
    app = FileDiffGUI(root)
    root.mainloop()

if __name__ == "__main__":
    main() 

file_diff_checker.py

import os
import difflib
from datetime import datetime
from typing import Dict, List, Tuple

class FolderDiffChecker:
    def __init__(self, folder_path: str):
        self.folder_path = folder_path
        self.previous_state: Dict[str, str] = {}
        self.current_state: Dict[str, str] = {}

    def scan_folder(self) -> Dict[str, str]:
        """扫描文件夹并返回文件内容的字典"""
        state = {}
        for root, _, files in os.walk(self.folder_path):
            for file in files:
                if file.endswith(('.py', '.js', '.java', '.cpp', '.txt')):  # 可以根据需要添加更多文件类型
                    file_path = os.path.join(root, file)
                    try:
                        with open(file_path, 'r', encoding='utf-8') as f:
                            content = f.read()
                            state[file_path] = content
                    except Exception as e:
                        print(f"无法读取文件 {file_path}: {str(e)}")
        return state

    def check_differences(self) -> List[Tuple[str, List[str]]]:
        """检查文件变化并返回差异列表"""
        self.current_state = self.scan_folder()
        differences = []

        # 检查新增和修改的文件
        for file_path, current_content in self.current_state.items():
            if file_path not in self.previous_state:
                # 对于新文件,添加更多信息
                differences.append((file_path, [
                    "新文件创建",
                    f"位置: {os.path.abspath(file_path)}",
                    f"大小: {len(current_content)} 字节"
                ]))
            else:
                previous_content = self.previous_state[file_path]
                if current_content != previous_content:
                    diff = list(difflib.unified_diff(
                        previous_content.splitlines(),
                        current_content.splitlines(),
                        fromfile=f"旧版本 - {os.path.basename(file_path)}",
                        tofile=f"新版本 - {os.path.basename(file_path)}",
                        lineterm=''
                    ))
                    differences.append((file_path, diff))

        # 检查删除的文件
        for file_path in self.previous_state:
            if file_path not in self.current_state:
                differences.append((file_path, [
                    "文件已删除",
                    f"原位置: {os.path.abspath(file_path)}"
                ]))

        # 更新previous_state为当前状态
        self.previous_state = self.current_state.copy()
        return differences

    def generate_report(self, differences: List[Tuple[str, List[str]]]) -> str:
        """生成更友好的差异报告"""
        if not differences:
            return "没有检测到文件变化。"

        report = f"文件变化报告 - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n"
        report += "=" * 50 + "\n\n"

        for file_path, diff in differences:
            # 添加更详细的文件信息
            report += f"文件: {os.path.basename(file_path)}\n"
            report += f"完整路径: {os.path.abspath(file_path)}\n"
            report += f"文件类型: {os.path.splitext(file_path)[1]}\n"
            report += "-" * 50 + "\n"
            
            # 添加文件变化类型的统计
            changes = {
                "added": 0,
                "removed": 0,
                "modified": 0
            }
            
            # 如果是新文件或已删除文件,直接显示状态
            if len(diff) == 1 and (diff[0] == "新文件创建" or diff[0] == "文件已删除"):
                report += f"状态: {diff[0]}\n"
                for info in diff[1:]:
                    report += f"{info}\n"
            else:
                # 统计变化
                for line in diff:
                    if line.startswith("+") and not line.startswith("+++"):
                        changes["added"] += 1
                    elif line.startswith("-") and not line.startswith("---"):
                        changes["removed"] += 1
                    elif line.startswith("@@"):
                        changes["modified"] += 1
                
                # 添加变化统计信息
                report += "变化统计:\n"
                report += f"- 新增行数: {changes['added']}\n"
                report += f"- 删除行数: {changes['removed']}\n"
                report += f"- 修改位置: {changes['modified']} 处\n\n"
                
                # 添加具体的变化内容
                report += "详细变化:\n"
                for line in diff:
                    # 美化输出格式
                    if line.startswith("+"):
                        report += f"\033[92m{line}\033[0m\n"  # 绿色显示新增
                    elif line.startswith("-"):
                        report += f"\033[91m{line}\033[0m\n"  # 红色显示删除
                    elif line.startswith("@@"):
                        report += f"\033[96m{line}\033[0m\n"  # 青色显示位置信息
                    else:
                        report += f"{line}\n"
            
            report += "\n" + "=" * 50 + "\n\n"

        return report

def main():
    # 使用示例
    folder_path = input("请输入要监控的文件夹路径: ")
    checker = FolderDiffChecker(folder_path)
    
    print("开始监控文件夹变化...")
    print("按 Ctrl+C 退出程序")
    
    try:
        while True:
            differences = checker.check_differences()
            if differences:
                report = checker.generate_report(differences)
                print("\n" + report)
            import time
            time.sleep(5)  # 每5秒检查一次变化
            
    except KeyboardInterrupt:
        print("\n程序已退出")

if __name__ == "__main__":
    main() 
Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐