第一百零一次闯荡江湖的无名游侠 - 2024年8月
[python+tkinter]实现选择目录将目录下多个文件夹内的文件复制到一个文件夹中
缘由：朋友有一个这样的需求，有三个文件夹，文件夹A内含有很多txt文件，文件夹B中也内含有很多txt文件，文件夹C中还是含有很多txt文件。需要把txt文件复制到同个文件夹中功能：选择目录将目录下多个文件夹内的文件复制到一个文件夹中运行图：下载地址：包含打包好的成品和源代码。python打包使用的是Pyinstaller打包。链接：https://ide.lanzouv.com/b0foqio5i密码:ao4j更新：2024.08.27 v1.1.01.增加线程防止界面复制时候处于 未响应 状态2.增加进度条显示2024.08.27 v1.0.0初始版本源代码：一共有4个文件：main.py、ui.py、control.py、logo.icomain.py# 导入布局文件 from ui import Win as MainWin # 导入窗口控制器 from control import Controller as MainUIController # 将窗口控制器 传递给UI app = MainWin(MainUIController()) if __name__ == "__main__": # 启动 app.mainloop()ui.pyfrom tkinter import * from tkinter.ttk import * class WinGUI(Tk): def __init__(self): super().__init__() self.__win() self.tk_label_m0c6l6hz = self.__tk_label_m0c6l6hz(self) self.tk_input_m0c6lpcn = self.__tk_input_m0c6lpcn(self) self.tk_button_m0c6lvy7 = self.__tk_button_m0c6lvy7(self) self.tk_label_m0c6mm3a = self.__tk_label_m0c6mm3a(self) self.tk_input_m0c6n6vi = self.__tk_input_m0c6n6vi(self) self.tk_button_m0c6nb3j = self.__tk_button_m0c6nb3j(self) self.tk_button_m0c7djh2 = self.__tk_button_m0c7djh2(self) self.tk_progressbar_m0d8ueyu = self.__tk_progressbar_m0d8ueyu(self) self.tk_label_m0d8xhee = self.__tk_label_m0d8xhee(self) self.tk_label_m0dhb051 = self.__tk_label_m0dhb051(self) def __win(self): self.title("多个文件夹内的文件复制到一个文件夹中_v1.1.0") # 设置窗口大小、居中 width = 572 height = 263 screenwidth = self.winfo_screenwidth() screenheight = self.winfo_screenheight() geometry = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2) self.geometry(geometry) self.resizable(width=False, height=False) def scrollbar_autohide(self, vbar, hbar, widget): """自动隐藏滚动条""" def show(): if vbar: vbar.lift(widget) if hbar: hbar.lift(widget) def hide(): if vbar: vbar.lower(widget) if hbar: hbar.lower(widget) hide() widget.bind("<Enter>", lambda e: show()) if vbar: vbar.bind("<Enter>", lambda e: show()) if vbar: vbar.bind("<Leave>", lambda e: hide()) if hbar: hbar.bind("<Enter>", lambda e: show()) if hbar: hbar.bind("<Leave>", lambda e: hide()) widget.bind("<Leave>", lambda e: hide()) def v_scrollbar(self, vbar, widget, x, y, w, h, pw, ph): widget.configure(yscrollcommand=vbar.set) vbar.config(command=widget.yview) vbar.place(relx=(w + x) / pw, rely=y / ph, relheight=h / ph, anchor='ne') def h_scrollbar(self, hbar, widget, x, y, w, h, pw, ph): widget.configure(xscrollcommand=hbar.set) hbar.config(command=widget.xview) hbar.place(relx=x / pw, rely=(y + h) / ph, relwidth=w / pw, anchor='sw') def create_bar(self, master, widget, is_vbar, is_hbar, x, y, w, h, pw, ph): vbar, hbar = None, None if is_vbar: vbar = Scrollbar(master) self.v_scrollbar(vbar, widget, x, y, w, h, pw, ph) if is_hbar: hbar = Scrollbar(master, orient="horizontal") self.h_scrollbar(hbar, widget, x, y, w, h, pw, ph) self.scrollbar_autohide(vbar, hbar, widget) def __tk_label_m0c6l6hz(self, parent): label = Label(parent, text="需要复制的文件夹：", anchor="center", ) label.place(x=14, y=8, width=116, height=30) return label def __tk_input_m0c6lpcn(self, parent): ipt = Entry(parent, ) ipt.place(x=14, y=40, width=454, height=30) return ipt def __tk_button_m0c6lvy7(self, parent): btn = Button(parent, text="选择路径", takefocus=False, ) btn.place(x=486, y=40, width=73, height=30) return btn def __tk_label_m0c6mm3a(self, parent): label = Label(parent, text="保存的路径：", anchor="center", ) label.place(x=14, y=80, width=81, height=30) return label def __tk_input_m0c6n6vi(self, parent): ipt = Entry(parent, ) ipt.place(x=14, y=112, width=454, height=30) return ipt def __tk_button_m0c6nb3j(self, parent): btn = Button(parent, text="选择路径", takefocus=False, ) btn.place(x=485, y=112, width=73, height=30) return btn def __tk_button_m0c7djh2(self, parent): btn = Button(parent, text="开始复制", takefocus=False, ) btn.place(x=302, y=178, width=224, height=71) return btn def __tk_progressbar_m0d8ueyu(self, parent): progressbar = Progressbar(parent, orient=HORIZONTAL, ) progressbar.place(x=14, y=184, width=195, height=30) return progressbar def __tk_label_m0d8xhee(self, parent): label = Label(parent, text="复制进度：", anchor="center", ) label.place(x=14, y=152, width=57, height=30) return label def __tk_label_m0dhb051(self, parent): label = Label(parent, text="", anchor="center", ) label.place(x=14, y=221, width=219, height=30) return label class Win(WinGUI): def __init__(self, controller): self.ctl = controller super().__init__() self.__event_bind() self.__style_config() self.ctl.init(self) def __event_bind(self): self.tk_button_m0c6lvy7.bind('<Button-1>', self.ctl.choosePatha) self.tk_button_m0c6nb3j.bind('<Button-1>', self.ctl.choosePathb) self.tk_button_m0c7djh2.bind('<Button-1>', self.ctl.startCopy) pass def __style_config(self): pass if __name__ == "__main__": win = WinGUI() win.mainloop()control.pyimport threading import os import shutil import tkinter as tk from tkinter import filedialog from tkinter.messagebox import showinfo class Controller: # 导入UI类后，替换以下的 object 类型，将获得 IDE 属性提示功能 ui: object def __init__(self): self.monitor_running = None def init(self, ui): self.ui = ui # TODO 组件初始化 赋值操作 def choosePatha(self,evt): if self.monitor_running == True: return False directory_path = filedialog.askdirectory( title="选择文件夹" ) # 显示选定的文件夹路径 if directory_path: # print("选择的文件夹:", directory_path) # 更新界面或其他逻辑 self.ui.tk_input_m0c6lpcn.delete(0, tk.END) self.ui.tk_input_m0c6lpcn.insert(0, directory_path) def choosePathb(self, evt): if self.monitor_running == True: return False directory_path = filedialog.askdirectory( title="选择文件夹" ) # 显示选定的文件夹路径 if directory_path: # print("选择的文件夹:", directory_path) # 更新界面或其他逻辑 self.ui.tk_input_m0c6n6vi.delete(0, tk.END) self.ui.tk_input_m0c6n6vi.insert(0, directory_path) def startCopy(self,evt): if self.monitor_running == True: return # 如果监控已经在运行，则不执行任何操作 fromPath = self.ui.tk_input_m0c6lpcn.get() savePath = self.ui.tk_input_m0c6n6vi.get() if fromPath == "" or savePath == "": showinfo(title="提示", message="两个路径都需要输入！") return False if fromPath in savePath: showinfo(title="提示", message="保存的路径不能选择到需要复制的文件夹内！") return False self.stop_event = threading.Event() self.thread = threading.Thread(target=self.update_counter, args=(fromPath,savePath)) self.thread.daemon = True self.thread.start() self.ui.tk_button_m0c6lvy7.config(state=tk.DISABLED) self.ui.tk_button_m0c6nb3j.config(state=tk.DISABLED) self.ui.tk_button_m0c7djh2.config(state=tk.DISABLED) self.ui.tk_input_m0c6lpcn.config(state="readonly") self.ui.tk_input_m0c6n6vi.config(state="readonly") self.monitor_running = True def update_counter(self, fromPath,savePath): self.CreateDir(savePath) fileNum = self.count_files_in_directory(fromPath) self.ui.tk_progressbar_m0d8ueyu.config(length=fileNum,maximum=fileNum) self.ui.tk_progressbar_m0d8ueyu["value"] = 0 self.ui.update() self.CopyFile(fromPath, savePath, fileNum) successfulText = "成功复制了" + str(fileNum) + "个文件" self.ui.tk_label_m0dhb051.config(text=successfulText) showinfo(title="提示", message="复制成功！") # 按钮启用 self.ui.tk_button_m0c6lvy7.config(state=tk.NORMAL) self.ui.tk_button_m0c6nb3j.config(state=tk.NORMAL) self.ui.tk_button_m0c7djh2.config(state=tk.NORMAL) self.ui.tk_input_m0c6lpcn.config(state="normal") self.ui.tk_input_m0c6n6vi.config(state="normal") self.monitor_running = False self.stop_event.set() # 设置停止事件 self.stop_event.clear() #置0 self.ui.tk_progressbar_m0d8ueyu["value"] = 0 self.ui.update() return True def count_files_in_directory(self,directory_path): # 初始化文件计数 file_count = 0 # 使用 os.walk 遍历文件夹及其子目录 for root, dirs, files in os.walk(directory_path): # 对于每个目录，累加文件数量 file_count += len(files) # 返回文件总数 return file_count def CopyFile(self,filepath, newPath, fileNum): # 获取当前路径下的文件名，返回List fileNames = os.listdir(filepath) for file in fileNames: # 将文件命加入到当前文件路径后面 newDir = filepath + '/' + file # 如果是文件 if os.path.isfile(newDir): newFile = newPath + '/'+ file shutil.copyfile(newDir, newFile) self.ui.tk_progressbar_m0d8ueyu["value"] += 1 self.ui.update() successfulText = "进度：" + str(self.ui.tk_progressbar_m0d8ueyu["value"]) + " / " + str(fileNum) self.ui.tk_label_m0dhb051.config(text=successfulText) # 如果不是文件，递归这个文件夹的路径 else: self.CopyFile(newDir, newPath, fileNum) def CreateDir(self,path): isExists = os.path.exists(path) # 判断结果 if not isExists: # 如果不存在则创建目录 os.makedirs(path) # print(path + ' 目录创建成功') # else: # 如果目录存在则不创建，并提示目录已存在 # print(path + ' 目录已存在')
1，找到需要处理的Word文档，将其扩展名修改为【.docx】，2，中Word文档，按F2键，对文档重新命名，把扩展名【.docx】改为【.zip】，按回车键，弹出提示，点击【是】3，如图，我们可以看到文档变成了一个压缩包，打开压缩包，找到Word文件夹，4，打开Word文件夹，然后展开media文件夹，可以看到所有图片5，选中所有图片，鼠标右击，选择【解压到指定文件夹】，图片提取成功了，任务完成。MS Office 2007及其之后的版本在保存文档时，默认是以 Office Open XML (OOXML) 格式存储，它本质上是一个zip压缩文件，只不过是把多种格式的文件打包在一起罢了，这些文档原样保留了嵌入的图片、音频、视频等文件，使用 WinRAR、7-zip 等压缩软件可以把它们解压出来。在Office办公三件套中，图片、音频、视频文件分别保存在这些路径下：Word为 \word\media\，Excel为 \xl\media\，PowerPoint 为 \ppt\media\。
我们常常会用到判断某个字符或者字符串是否包含中文，英文，特殊符号等等。这时候可以通过判断Unicode所在区间来确定某个字符所处类型。当然可以通过直接判断Unicode码，但是鉴于习惯，以下提供的是Unicode码对应的数字区间。毕竟字符的本质也就是通过二进制进行存储编码的而已。基本汉字：[0x4e00,0x9fa5](或十进制[19968,40869]) 数字：[0x 0030,0x0039](或十进制[48, 57]) 小写字母：[0x0061,0x007a](或十进制[97, 122]) 大写字母：[0x0041,0x005a](或十进制[65, 90]) Unicode都是两个字节，由于长度统一，所以比较适合程序处理。 再来一个比较完整的Unicode分布： 0000-007F：C0控制符及基本拉丁文 (C0 Control and Basic Latin) 0080-00FF：C1控制符及拉丁文补充-1 (C1 Control and Latin 1 Supplement) 0100-017F：拉丁文扩展-A (Latin Extended-A) 0180-024F：拉丁文扩展-B (Latin Extended-B) 0250-02AF：国际音标扩展 (IPA Extensions) 02B0-02FF：空白修饰字母 (Spacing Modifiers) 0300-036F：结合用读音符号 (Combining Diacritics Marks) 0370-03FF：希腊文及科普特文 (Greek and Coptic) 0400-04FF：西里尔字母 (Cyrillic) 0500-052F：西里尔字母补充 (Cyrillic Supplement) 0530-058F：亚美尼亚语 (Armenian) 0590-05FF：希伯来文 (Hebrew) 0600-06FF：阿拉伯文 (Arabic) 0700-074F：叙利亚文 (Syriac) 0750-077F：阿拉伯文补充 (Arabic Supplement) 0780-07BF：马尔代夫语 (Thaana) 07C0-077F：西非書面語言 (N'Ko) 0800-085F：阿维斯塔语及巴列维语 (Avestan and Pahlavi) 0860-087F：Mandaic 0880-08AF：撒马利亚语 (Samaritan) 0900-097F：天城文书 (Devanagari)来源：https://blog.csdn.net/weixin_34206263/article/details/11203186
1、删除字符串中的指定符号对字符串中间的特殊符号或制定字符串的删除，常用replace函数。（注：replace方法不能改变原始字符串，替换出来的字符串为内存新建字符串，并未改变原始变量指针。）replace函数格式：str.replace(old, new, count)str：已知原始给定字符串old： 将被替换的制定字符（串）new：新字符串，用于替换old字符串。count：最大替换次数注：需要删除而非替换的作用时仅需将new设为''即可举例：#删除顿号 str1 = "212、Python用replace()函数删除制定 符号" str2 = str1.replace('、', '') print(str2) # "212Python用replace()函数删除制定 符号" #删除字符串"函数" str1 = "212、Python用replace()函数删除制定 符号" str2 = str1.replace('函数', '') print(str2) # "212、Python用replace()删除制定 符号"2、删除字符串中的空格在Python中删除字符串中的空格的常用函数及作用如下str.strip()： 删除开头和结尾的空格str.lstrip()： 删除开头（左侧）的空格str.rstrip()： 删除结尾（右侧）的空格str.replace('', '')：删除字符串中的所有空格举例：str1 = " 212、Python用replace()函数删除制定 符号 " print(str1.strip()) # "212、Python用replace()函数删除制定 符号" print(str1.lstrip()) # "212、Python用replace()函数删除制定 符号 " print(str1.rstrip()) # " 212、Python用replace()函数删除制定 符号" print(str1.replace(' ', '')) # "212、Python用replace()函数删除制定符号"3、删除字符串中的所有符号，只保留汉字常用字符unicode的编码范围：数字：0-9 汉字：一-龥 大写字母：A-Z 小写字母：a-z 英文字母：A-z注：更多的编码范围可参考：https://diyibailingyici.chuangdangjianghudewumingyouxia.cn/archives/367.html说明：只保留汉字 等价于 将所有非汉字的字符全部删除，因此对非汉字（^一-龥）全部用replace函数替换即可举例：import re str1 = " 212、Python用replace()函数删除制定 符号 " str2 = re.sub('([^一-龥])', '', str1) print(str2) # "用函数删除制定符号"4、删除字符串中的所有符号，只保留字符串中的汉字和数字说明：逻辑同3，只保留汉字和数字 等价于 将所有非汉字的字符全部删除。因此对非汉字（^一-龥）和非数字（^0-9）全部用replace函数替换即可，重点在于如何将unicode编码范围进行拼接。举例：import re str1 = " 212、Python用replace()函数删除制定 符号 " str2 = re.sub('([^一-龥0-9])', '', str1) print(str2) # "212用函数删除制定符号"来源：https://blog.csdn.net/O_nice/article/details/124043331
win电脑被解锁后钉钉或飞书机器人提醒工具
新手写一个易语言小工具。一个电脑win + L 锁屏，被解锁后就给钉钉或者飞书机器发送提醒。用途：知道有人解锁了你的电脑。起因：公司电脑挂着向日葵，一直开机的。但是怕密码被别人知道了，在我没连接远程时候解锁电脑弄一些东西。找了一下没找到，然后就自己试着弄了一个这个。v1.2版本：1.增加了开机启动（但是不完美，开启启动后没有发送）2.用了开源UI（未闻花名UI）3.修改了解锁后再锁定密码还会被保留在编辑框里面_7月6日修改下载地址在最下面v1.1版本：1.增加了选择飞书机器2.托盘显示3.锁界面(貌似没什么用)_7月5日修改下载地址在最下面v1.0版本：软件中的关键字就是钉钉机器人安全设置中的自定义关键词：Q：为什么没有加签？A：因为我不会写签名算法。下面是软件截图：下面是查毒链接蓝奏云下载：https://ide.lanzoum.com/b00pvknwh密码: e2d5