自己动手写一个U盘拷贝小工具

时间:2024-02-20 19:45:37

这是五一期间,参照知乎上一篇的文章十行代码--用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盘所有的目录和文件拷进硬盘,自动在硬盘上创建一个文件夹来存储这些拷贝数据,还可以按照需要拷贝多份(默认是拷贝一份)

现将源码附上:

  1 \'\'\'
  2 version v1.0
  3 1. 实现了简单的pycharm运行功能
  4 2. 利用追加目录名的方法来实现添加n个目录,但受到目录名长度的限制
  5 
  6 version v2.0
  7 1. 利用时间戳表示目录名
  8 2. 利用tkinter实现了简单的GUI
  9 
 10 version v3.0
 11 1. 修改了部分GUI界面字符
 12 2. 利用datetime获取当前时间,并转化为字符串形式添加到目录
 13 
 14 version v4.0
 15 1. 修改了部分GUI界面
 16 
 17 version v5.0
 18 1. 限定了udisk_path, backup_path和num的范围
 19 2. 对以上输入进行容错处理
 20 3. 添加了计算程序运行时间的功能
 21 4. 添加了输入提示
 22 5. 不区分盘符的大小写
 23 
 24 version v6.0
 25 1. 更新了使用说明和字体、颜色
 26 2. 更新了软件图标
 27 3. 解决盘符为G:/的U盘不插入,不会弹出提示的问题。即在异常处理里增加了一个PermissionError的异常。
 28 
 29 version v6.1
 30 1. 解决了当U盘盘符为g:/, h:/时,弹出的错误信息
 31 2. 给拷贝次数一个默认值1
 32 3. 更新了使用说明
 33 \'\'\'
 34 
 35 
 36 
 37 import os, shutil, sys
 38 import time, datetime, tkinter
 39 import tkinter.messagebox as mb
 40 
 41 class Udisk:
 42 
 43     def __init__(self, backup_path = "D:/", udisk_path = "H:/", num = 1):
 44         self.backup_path = backup_path
 45         self.udisk_path = udisk_path
 46         self.num = num
 47 
 48     def resource_path(self, relative):
 49         if hasattr(sys, "_MEIPASS"):
 50             return os.path.join(sys._MEIPASS, relative)
 51         return os.path.join(relative)
 52 
 53     def copy_GUI(self):
 54         root = tkinter.Tk()
 55         root.title("U盘拷贝小工具 v6.1")
 56         root.geometry("400x260")
 57         icopath = self.resource_path(r"favicon-20180501101520441.ico")
 58         if os.path.exists(icopath):
 59             root.iconbitmap(icopath)
 60 
 61         tkinter.Label(root, text = "U盘盘符(如G:/)", font = ("华文中宋", 12)).grid(row = 0)
 62         tkinter.Label(root, text = "拷贝目录(如D:/)", font = ("华文中宋", 12)).grid(row = 1)
 63         tkinter.Label(root, text = "拷贝次数(如3)", font = ("华文中宋", 12)).grid(row = 2)
 64 
 65 
 66         self.input_1 = tkinter.Entry(root)
 67         self.input_2 = tkinter.Entry(root)
 68         self.input_3 = tkinter.Entry(root)
 69 
 70         self.input_3.insert(10, "1")
 71 
 72         self.input_1.grid(row = 0, column = 1)
 73         self.input_2.grid(row = 1, column = 1)
 74         self.input_3.grid(row = 2, column = 1)
 75 
 76         tkinter.Button(root, text = "ok", font = ("Arial", 12), background = "MediumSlateBlue", command = self.run).grid(row=3,  pady=15, column=0)
 77         tkinter.Button(root, text = "exit", font = ("Arial", 12), background = "DarkGray", command = root.quit).grid(row=3, pady=15, column=1)
 78 
 79         tkinter.Label(root, text = "使用说明:\n1.本软件适用于windows系统;\n2.默认以/作为目录分隔符;\n3.目录名不能包含特殊字符\n4.默认拷贝次数为1", justify = "left", font = ("隶书", 12), pady = 20).grid(row = 4)
 80 
 81 
 82         root.mainloop()
 83 
 84     def dirExists(self):
 85         while True:
 86             if os.path.exists(self.backup_path) == True:
 87                 print("copytree方法的路径%s不能是已存在的!" % self.backup_path)
 88                 now = datetime.datetime.now()
 89                 self.backup_path += now.strftime(\'%Y-%m-%d %H-%M-%S.%f\')
 90                 print("程序自动将路径重命名为: %s" % self.backup_path)
 91                 return self.dirExists()
 92             else:
 93                 break
 94 
 95     def copyUdisk(self):
 96         try:
 97             self.flag = True
 98             file_list = []
 99             content = os.listdir(self.udisk_path)
100             self.dirExists()
101         except FileNotFoundError:
102             print("对不起,U盘不存在,请插入U盘重试! ")
103             return False
104         except PermissionError:
105             print("对不起,U盘不存在,请插入U盘重试! ")
106             self.flag = False
107         else:
108             for item_1 in content:
109                 if os.path.isfile(os.path.join(self.udisk_path, item_1)) == False:
110                     shutil.copytree(os.path.join(self.udisk_path, item_1), self.backup_path + "/" + item_1)
111                 else:
112                     file_list.append(item_1)
113             for item_2 in file_list:
114                 shutil.copy(os.path.join(self.udisk_path, item_2), self.backup_path + "/")
115             print("已拷贝至", self.backup_path)
116             return True
117 
118     def run(self):
119         time_1 = time.time()
120         try:
121             self.udisk_path = self.input_1.get()
122             self.backup_path = self.input_2.get()
123             self.num = self.input_3.get()
124             print(self.num)
125             standard_backup_path = ["C:/", "c:/", "D:/", "d:/", "E:/", "e:/", "F:/", "f:/"]
126             standard_udisk_path = ["G:/", "g:/", "H:/", "h:/"]
127             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 == ""):
128                 for i in range(int(self.num)):
129                     my_copy = Udisk(self.backup_path, self.udisk_path, self.num)
130                     if my_copy.copyUdisk() == False:
131                         mb.showerror("错误", "对不起,U盘不存在,请插入U盘重试! ")
132                         break
133                     elif my_copy.flag == False:
134                         mb.showerror("错误", "对不起,U盘盘符不对应,请重试! ")
135                         break
136                     elif i == (int(self.num) - 1):
137                         time_2 = time.time()
138                         total_time = time_2 - time_1
139                         output = "已拷贝成功:)"
140                         mb.showinfo("结果", output)
141                         mb.showinfo("共耗时", str(total_time)+"")
142             elif self.udisk_path[:] not in standard_udisk_path:
143                 if self.udisk_path == "":
144                     mb.showerror("输入错误", "U盘盘符不能为空,请重试! ")
145                 else:
146                     mb.showerror("输入错误", "输入U盘盘符错误,请重试! ")
147             elif self.backup_path[0:3] not in standard_backup_path:
148                 if self.backup_path == "":
149                     mb.showerror("输入错误", "拷贝目录不能为空,请重试! ")
150                 else:
151                     mb.showerror("输入错误", "输入拷贝目录错误,请重试! ")
152         except ValueError:
153                 mb.showerror("输入错误", "输入拷贝次数错误,请重试! ")
154 
155 mycopy = Udisk()
156 mycopy.copy_GUI()