自己动手写一个U盘拷贝小工具
这是五一期间,参照知乎上一篇的文章《十行代码--用python写一个USB病毒》写成的,最初只是单纯的想写成死循环,直到文件占满硬盘为止,第一个遇到的问题是,拷贝到硬盘之后,由于要无限次拷贝,所以每次的文件夹的名字不能重复,对于这个问题,开始是采用追加的方式,比如第一个文件夹叫udisk_bakcup,第二个文件夹就叫udisk_backup_demo,第三个叫udisk_backup_demo_demo...看到的效果是:
这样肯定是不行的,因为文件夹名字的长度好像不能超过256个字节,受一位开发同学的启发,用时间戳来表示,看到的效果明显好多了
后来想,能不能不写死循环,而是根据用户的需要选择拷贝次数,能不能做成界面,一切在遇到tkinter和PyInstaller后得到了解决
界面化实现过程不太容易,遇到的问题参见:《解决: PyInstaller打包后exe文件打开时出现failed to execute script》
生成图标后,还有一个问题:打包后生成的exe文件打开后,工具左上角的图标并没有加载进来,而直接运行代码是ok的(见上图)
利用if判断,做了一定的容错处理,那时我不知道还可以用正则做这件事,如果知道,可能会简化一下代码
再后来发现当U盘中的目录很大时,几百M到几个G,拷贝容易出现卡死的情况,可能由于是单线程,所以想着用多线程或协程的方法优化一下,谁知后来越来越忙就放下了,等到有机会再试一把
这个工具还是很好用的,可以将U盘所有的目录和文件拷进硬盘,自动在硬盘上创建一个文件夹来存储这些拷贝数据,还可以按照需要拷贝多份(默认是拷贝一份)
现将源码附上:
- '''
- version v1.0
- 1. 实现了简单的pycharm运行功能
- 2. 利用追加目录名的方法来实现添加n个目录,但受到目录名长度的限制
- version v2.0
- 1. 利用时间戳表示目录名
- 2. 利用tkinter实现了简单的GUI
- version v3.0
- 1. 修改了部分GUI界面字符
- 2. 利用datetime获取当前时间,并转化为字符串形式添加到目录
- version v4.0
- 1. 修改了部分GUI界面
- version v5.0
- 1. 限定了udisk_path, backup_path和num的范围
- 2. 对以上输入进行容错处理
- 3. 添加了计算程序运行时间的功能
- 4. 添加了输入提示
- 5. 不区分盘符的大小写
- version v6.0
- 1. 更新了使用说明和字体、颜色
- 2. 更新了软件图标
- 3. 解决盘符为G:/的U盘不插入,不会弹出提示的问题。即在异常处理里增加了一个PermissionError的异常。
- version v6.1
- 1. 解决了当U盘盘符为g:/, h:/时,弹出的错误信息
- 2. 给拷贝次数一个默认值1
- 3. 更新了使用说明
- '''
- import os, shutil, sys
- import time, datetime, tkinter
- import tkinter.messagebox as mb
- class Udisk:
- def __init__(self, backup_path = "D:/", udisk_path = "H:/", num = 1):
- self.backup_path = backup_path
- self.udisk_path = udisk_path
- self.num = num
- def resource_path(self, relative):
- if hasattr(sys, "_MEIPASS"):
- return os.path.join(sys._MEIPASS, relative)
- return os.path.join(relative)
- def copy_GUI(self):
- root = tkinter.Tk()
- root.title("U盘拷贝小工具 v6.1")
- root.geometry("400x260")
- icopath = self.resource_path(r"favicon-20180501101520441.ico")
- if os.path.exists(icopath):
- root.iconbitmap(icopath)
- tkinter.Label(root, text = "U盘盘符(如G:/)", font = ("华文中宋", 12)).grid(row = 0)
- tkinter.Label(root, text = "拷贝目录(如D:/)", font = ("华文中宋", 12)).grid(row = 1)
- tkinter.Label(root, text = "拷贝次数(如3)", font = ("华文中宋", 12)).grid(row = 2)
- self.input_1 = tkinter.Entry(root)
- self.input_2 = tkinter.Entry(root)
- self.input_3 = tkinter.Entry(root)
- self.input_3.insert(10, ")
- self.input_1.grid(row = 0, column = 1)
- self.input_2.grid(row = 1, column = 1)
- self.input_3.grid(row = 2, column = 1)
- tkinter.Button(root, text = "ok", font = ("Arial", 12), background = "MediumSlateBlue", command = self.run).grid(row=3, pady=15, column=0)
- tkinter.Button(root, text = "exit", font = ("Arial", 12), background = "DarkGray", command = root.quit).grid(row=3, pady=15, column=1)
- tkinter.Label(root, text = "使用说明:\n1.本软件适用于windows系统;\n2.默认以/作为目录分隔符;\n3.目录名不能包含特殊字符\n4.默认拷贝次数为1", justify = "left", font = ("隶书", 12), pady = 20).grid(row = 4)
- root.mainloop()
- def dirExists(self):
- while True:
- if os.path.exists(self.backup_path) == True:
- print("copytree方法的路径%s不能是已存在的!" % self.backup_path)
- now = datetime.datetime.now()
- self.backup_path += now.strftime('%Y-%m-%d %H-%M-%S.%f')
- print("程序自动将路径重命名为: %s" % self.backup_path)
- return self.dirExists()
- else:
- break
- def copyUdisk(self):
- try:
- self.flag = True
- file_list = []
- content = os.listdir(self.udisk_path)
- self.dirExists()
- except FileNotFoundError:
- print("对不起,U盘不存在,请插入U盘重试! ")
- return False
- except PermissionError:
- print("对不起,U盘不存在,请插入U盘重试! ")
- self.flag = False
- else:
- for item_1 in content:
- if os.path.isfile(os.path.join(self.udisk_path, item_1)) == False:
- shutil.copytree(os.path.join(self.udisk_path, item_1), self.backup_path + "/" + item_1)
- else:
- file_list.append(item_1)
- for item_2 in file_list:
- shutil.copy(os.path.join(self.udisk_path, item_2), self.backup_path + "/")
- print("已拷贝至", self.backup_path)
- return True
- def run(self):
- time_1 = time.time()
- try:
- self.udisk_path = self.input_1.get()
- self.backup_path = self.input_2.get()
- self.num = self.input_3.get()
- print(self.num)
- standard_backup_path = ["C:/", "c:/", "D:/", "d:/", "E:/", "e:/", "F:/", "f:/"]
- standard_udisk_path = ["G:/", "g:/", "H:/", "h:/"]
- if self.backup_path[0:3] in standard_backup_path and self.udisk_path[:] in standard_udisk_path and (type(int(self.num)) == int or self.num == ""):
- for i in range(int(self.num)):
- my_copy = Udisk(self.backup_path, self.udisk_path, self.num)
- if my_copy.copyUdisk() == False:
- mb.showerror("错误", "对不起,U盘不存在,请插入U盘重试! ")
- break
- elif my_copy.flag == False:
- mb.showerror("错误", "对不起,U盘盘符不对应,请重试! ")
- break
- elif i == (int(self.num) - 1):
- time_2 = time.time()
- total_time = time_2 - time_1
- output = "已拷贝成功:)"
- mb.showinfo("结果", output)
- mb.showinfo("共耗时", str(total_time)+"秒")
- elif self.udisk_path[:] not in standard_udisk_path:
- if self.udisk_path == "":
- mb.showerror("输入错误", "U盘盘符不能为空,请重试! ")
- else:
- mb.showerror("输入错误", "输入U盘盘符错误,请重试! ")
- elif self.backup_path[0:3] not in standard_backup_path:
- if self.backup_path == "":
- mb.showerror("输入错误", "拷贝目录不能为空,请重试! ")
- else:
- mb.showerror("输入错误", "输入拷贝目录错误,请重试! ")
- except ValueError:
- mb.showerror("输入错误", "输入拷贝次数错误,请重试! ")
- mycopy = Udisk()
- mycopy.copy_GUI()
自己动手写一个U盘拷贝小工具的更多相关文章
- 用 C# 写一个 Redis 数据同步小工具
用 C# 写一个 Redis 数据同步小工具 Intro 为了实现 redis 的数据迁移而写的一个小工具,将一个实例中的 redis 数据同步到另外一个实例中.(原本打算找一个已有的工具去做,找了一 ...
- 动手写一个简单版的谷歌TPU-指令集
系列目录 谷歌TPU概述和简化 基本单元-矩阵乘法阵列 基本单元-归一化和池化(待发布) TPU中的指令集 SimpleTPU实例: (计划中) 拓展 TPU的边界(规划中) 重新审视深度神经网络中的 ...
- 死磕 java线程系列之自己动手写一个线程池
欢迎关注我的公众号"彤哥读源码",查看更多源码系列文章, 与彤哥一起畅游源码的海洋. (手机横屏看源码更方便) 问题 (1)自己动手写一个线程池需要考虑哪些因素? (2)自己动手写 ...
- 动手写一个简单的Web框架(Werkzeug路由问题)
动手写一个简单的Web框架(Werkzeug路由问题) 继承上一篇博客,实现了HelloWorld,但是这并不是一个Web框架,只是自己手写的一个程序,别人是无法通过自己定义路由和返回文本,来使用的, ...
- 动手写一个简单版的谷歌TPU-矩阵乘法和卷积
谷歌TPU是一个设计良好的矩阵计算加速单元,可以很好的加速神经网络的计算.本系列文章将利用公开的TPU V1相关资料,对其进行一定的简化.推测和修改,来实际编写一个简单版本的谷歌TPU.计划实现到行为 ...
- 死磕 java同步系列之自己动手写一个锁Lock
问题 (1)自己动手写一个锁需要哪些知识? (2)自己动手写一个锁到底有多简单? (3)自己能不能写出来一个完美的锁? 简介 本篇文章的目标一是自己动手写一个锁,这个锁的功能很简单,能进行正常的加锁. ...
- 开源一个Mac漂亮的小工具 PPRows for Mac, 在Mac上优雅的计算你写了多少行代码
开源一个Mac漂亮的小工具 PPRows for Mac, 在Mac上优雅的计算你写了多少行代码. 开源地址: https://github.com/jkpang/PPRows
- 自己动手写一个服务网关-java
自己动手写一个服务网关 原文链接:https://www.cnblogs.com/bigben0123/p/9252444.html 引言 什么是网关?为什么需要使用网关? 如图所示,在不使用网关的情 ...
- 动手写一个简单的Web框架(模板渲染)
动手写一个简单的Web框架(模板渲染) 在百度上搜索jinja2,显示的大部分内容都是jinja2的渲染语法,这个不是Web框架需要做的事,最终,居然在Werkzeug的官方文档里找到模板渲染的代码. ...
随机推荐
- 斯坦福大学Andrew Ng - 机器学习笔记(1) -- 单变量&多变量线性回归
大概用了一个月,Andrew Ng老师的机器学习视频断断续续看完了,以下是个人学习笔记,入门级别,权当总结.笔记难免有遗漏和误解,欢迎讨论. 鸣谢:中国海洋大学黄海广博士提供课程视频和个人笔记,在此深 ...
- Could not create ServerSocket on address 0.0.0.0/0.0.0.0:9083
遇到这种情况大家都找不到头绪,是因为你开始运行了hive的metastore,可以输入jps 然后出现如下: 红线所示就是hive metastore的进程 为了重新启动,需要把这个进杀掉: kill ...
- active scaffold
模板文件路径:/.rvm/gems/ruby-2.2.3/gems/active_scaffold-3.5.3/app/views/active_scaffold_overrides
- b和strong,i与em的区别
html语义化标签: 1)title与h1的区别 title与H1是不能划等号的 1.H1是大标题的意思.一般出现网页文章页面,作用如同一张报纸的大标题,使用读者在没看内容之前就 大概了解本文的旨意, ...
- 【CodeChef】Small factorials(BigInteger笔记)
You are asked to calculate factorials of some small positive integers. Input An integer t, 1<=t&l ...
- linux基础三---网络基础&软件包管理
一 ifconfig:显示所有正在启动的网卡的详细信息或设定系统中网卡的IP地址. ifconfig eno16777736 down/up 关闭/开启 eno16777736 网卡 ifconf ...
- Django框架之cookie和session及开发登录功能
1.cookie是什么? Web应用程序是使用HTTP协议传输数据的.HTTP协议是无状态的协议.一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的连接.这就意味着服务器无法从 ...
- 在各种Linux发行版上安装Git的教程
Git是一个流行的开源版本控制系统(VCS),最初是为Linux环境开发的.跟CVS或者SVN这些版本控制系统不同的是,Git的版本控制被认为是“分布式的”,某种意义上,git的本地工作目录可以作为一 ...
- MyBatis联合查询association使用
1.需求 两张表 channels(频道表) member(会员表) 频道表里面有会员id,查询频道列表的时候需要关联查询出会员的名称,头像等信息 . 2.channels.xml定义,配置主要在这 ...
- 【BZOJ2733】永无乡[HNOI2012](splay启发式合并or线段树合并)
题目大意:给你一些点,修改是在在两个点之间连一条无向边,查询时求某个点能走到的点中重要度第k大的点.题目中给定的是每个节点的排名,所以实际上是求第k小:题目求的是编号,不是重要度的排名.我一开始差点被 ...