1 #system module
2 importos3 importre4 importtkinter5 importtkinter.messagebox6 importtkinter.filedialog7 importtkinter.ttk8 importsys9 importlogging10
11 logger = logging.getLogger(__name__)12
13 def create_logger(filename="log.txt", level=logging.INFO, console_swtich =True):14 #获取logger实例,如果参数为空则返回root logger
15 #logger = logging.getLogger(__name__)
16
17 #创建日志输出格式
18 formatter = logging.Formatter("%(asctime)s - %(filename)s[line:%(lineno)d][%(funcName)s] - %(levelname)s - %(message)s")19
20 #指定输出的文件路径
21 file_handler =logging.FileHandler(filename)22 #设置文件处理器格式
23 file_handler.setFormatter(formatter)24
25 #为logger添加的日志处理器
26 logger.addHandler(file_handler)27
28 #控制台日志
29 ifconsole_swtich:30 console_handler =logging.StreamHandler(sys.stdout)31 console_handler.formatter =formatter32 logger.addHandler(console_handler)33
34 #指定日志的最低输出级别,默认为warn级别
35 logger.setLevel(level)36
37 returnlogger38
39 classmodify_string():40 #界面布局方法
41 def __init__(self):42 #创建界面,并且保存到成员属性中
43 self.root =tkinter.Tk()44 self.root.minsize(400, 170)45 self.root.resizable(0, 0)46 self.root.title("批量修改字符串")47
48 #文件夹路径
49 self.path =tkinter.StringVar()50 self.path.set("")51
52 #选项
53 self.folder_name =tkinter.IntVar()54 self.file_name =tkinter.IntVar()55 self.file_content =tkinter.IntVar()56
57 #字符串
58 self.string_old =tkinter.StringVar()59 self.string_new =tkinter.StringVar()60
61 #进度
62 self.progress =tkinter.StringVar()63 self.progress.set("开始修改")64
65 #界面布局
66 self.menus()67 self.layout()68 self.root.mainloop()69
70 defmenus(self):71 #添加菜单
72
73 #创建总菜单
74 allmenu =tkinter.Menu(self.root)75
76 #添加子菜单1
77 debugmenu = tkinter.Menu(allmenu, tearoff=0)78 debugmenu.add_command(label="日志",79 command=self.log)80
81 allmenu.add_cascade(label="调试",82 menu=debugmenu)83
84 #添加子菜单2
85 helpmenu = tkinter.Menu(allmenu, tearoff=0)86
87 #添加选项卡
88 helpmenu.add_command(label='规则',89 command=self.rule)90 helpmenu.add_command(label='版本说明',91 command=self.release_note)92 helpmenu.add_command(label='关于',93 command=self.about)94
95 allmenu.add_cascade(label='帮助',96 menu=helpmenu)97
98 tkinter.ttk.Separator(self.root, orient="horizontal").pack(fill="x", padx=0)99
100
101 self.root.config(menu=allmenu)102
103 deflayout(self):104 #布局
105 #文件夹路径
106 path_description =tkinter.Label(self.root,107 font=("宋体", 10),108 fg="blue",109 anchor="w",110 text="文件夹路径")111 path_description.place(x=5, y=10, width=70, height=20)112
113 path_show =tkinter.Label(self.root,114 bd=3,115 bg='white',116 font=("宋体", 10),117 anchor="e",118 textvariable=self.path)119 path_show.place(x=80, y=10, width=250, height=20)120
121 button_path =tkinter.Button(self.root,122 text='选择',123 command=self.select_path)124 button_path.place(x=335, y=10, width=60, height=20)125
126 #选项
127 option =tkinter.Label(self.root,128 font=("宋体", 10),129 fg="blue",130 anchor="w",131 text="修改选项")132 option.place(x=5, y=40, width=70, height=20)133
134 folder_select =tkinter.Checkbutton(self.root,135 text="文件夹名称",136 anchor="w",137 variable=self.folder_name)138 folder_select.place(x=80, y=40, width=100, height=20)139
140 folder_select =tkinter.Checkbutton(self.root,141 text="文件名称",142 anchor="w",143 variable=self.file_name)144 folder_select.place(x=185, y=40, width=100, height=20)145
146 folder_select =tkinter.Checkbutton(self.root,147 text="文件内容",148 anchor="w",149 variable=self.file_content)150 folder_select.place(x=290, y=40, width=100, height=20)151
152 #字符串
153 tkinter.Label(self.root,154 font=("宋体", 10),155 fg="blue",156 anchor="w",157 text="原字符串").place(x=5, y=70, width=70, height=20)158 source_text =tkinter.Entry(self.root,159 textvariable=self.string_old)160 source_text.place(x=80, y=70, width=310, height=20)161
162 tkinter.Label(self.root,163 font=("宋体", 10),164 fg="blue",165 anchor="w",166 text="新字符串").place(x=5, y=100, width=70, height=20)167 source_text =tkinter.Entry(self.root,168 textvariable=self.string_new)169 source_text.place(x=80, y=100, width=310, height=20)170
171 #开始修改
172 button_start =tkinter.Button(self.root,173 font=("宋体", 12),174 text="开始修改",175 command=self.start)176 button_start.place(x=165, y=130, width=70, height=30)177
178 defmatchcase(self, word):179 returnword180 #def rmodify(m):
181 ## re.sub会将匹配到的对象,循环调用modify方法传入
182 #183 ## 获取匹配的文本
184 #text = m.group()
185 #186 #if text.isupper():
187 ## 如果文本全部是大写,就返回word的全部大写模式
188 #return word.upper()
189 #elif text.islower():
190 ## 如果文本全部是小写,就返回word的全部小写模式
191 #return word.lower()
192 #elif len(text) > 0 and text[0].isupper():
193 ## 如果文本是首字母大写,就返回word的首字母大写模式
194 #return word.capitalize()
195 #else:
196 ## 其他情况,直接返回word
197 #return word
198 #199 #return modify
200
201 defmodify(self, path):202 #修改当前文件夹名称
203 if self.folder_name.get() == 1:204 folder =os.path.basename(path)205 folder =re.sub(self.string_old.get(),206 self.matchcase(self.string_new.get()),207 #flags=re.IGNORECASE,
208 folder)209 os.rename(path, os.path.join(os.path.dirname(path), folder))210 path =os.path.join(os.path.dirname(path), folder)211
212 filenames =os.listdir(path)213 logger.info(f"file list {filenames}")214
215 for filename infilenames:216 domain =os.path.abspath(path)217 file_path =os.path.join(domain, filename)218
219 #递归修改子文件名称、文件名称、文件内容
220 ifos.path.isdir(file_path):221 if self.folder_name.get() == 1:222 filename =re.sub(self.string_old.get(),223 self.matchcase(self.string_new.get()),224 #flags=re.IGNORECASE,
225 filename)226 os.rename(file_path, os.path.join(domain, filename))227 file_path =os.path.join(domain, filename)228
229 logger.debug(f"enter folder {file_path}")230 self.modify(file_path)231 logger.debug(f"exit folder {file_path}\n")232 continue
233
234 #修改文件名称
235 if self.file_name.get() == 1:236 filename =re.sub(self.string_old.get(),237 self.matchcase(self.string_new.get()),238 #flags=re.IGNORECASE,
239 filename)240 os.rename(file_path, os.path.join(domain, filename))241 file_path =os.path.join(domain, filename)242
243 #修改文件内容
244 if self.file_content.get() == 1:245 format = file_path.split(".")[-1]246 if format != "c" and format != "h" and format != "txt":247 logger.info(f"can not process {file_path}")248 continue;249
250 fread = open(file_path, 'r')251 fwrite = open("%s.backup" % file_path, 'w')252
253 whileTrue:254 line =fread.readline()255 if len(line) >0:256 line =re.sub(self.string_old.get(),257 self.matchcase(self.string_new.get()),258 #flags=re.IGNORECASE,
259 line)260 fwrite.write(line)261 else:262 break
263 fread.close()264 fwrite.close()265 os.remove(file_path)266 os.rename("%s.backup" %file_path, file_path)267
268 defstart(self):269 if self.path.get() == "":270 tkinter.messagebox.showinfo('错误', "请选择文件夹路径!")271 else:272 logger.info(f'''路径:"{self.path.get()}"''')273 logger.info("修改选项:")274 option_count =0275 if self.folder_name.get() == 1:276 option_count = option_count + 1
277 logger.info(f"{option_count}. 文件夹名称")278 if self.file_name.get() == 1:279 option_count = option_count + 1
280 logger.info(f"{option_count}. 文件名称")281 if self.file_content.get() == 1:282 option_count = option_count + 1
283 logger.info(f"{option_count}. 文件内容")284 logger.info(f"原字符串:{self.string_old.get()}")285 logger.info(f"新字符串:{self.string_new.get()}")286 self.modify(self.path.get())287 tkinter.messagebox.showinfo('结果', "修改完成")288
289 deflog(self):290 os.startfile("log.txt")291 #domain = os.path.abspath(os.getcwd())
292 #log_path = os.path.join(domain, "log")
293 #294 #log = open(log_path, 'r')
295 #log.close()
296
297 defrule(self):298 tkinter.messagebox.showinfo('批量修改字符串规则',299 "1.修改当前文件夹及子文件夹的名称;\n"
300 "2.修改当前文件夹及子文件夹下所有文件的名称;\n"
301 "3.修改当前文件夹及子文件夹下所有文件的内容;\n")302
303 defabout(self):304 tkinter.messagebox.showinfo('批量修改字符串',305 "作者:Risun_Lee\n"
306 "版本: V1.0\n"
307 "发布日期: 2020年9月8日\n")308
309 defrelease_note(self):310 tkinter.messagebox.showinfo('版本说明',311 "V1.0:\n"
312 "1.支持文件夹名称、文件名称的修改;\n"
313 "2.支持txt、c、h文件内容的修改;\n")314
315 defselect_path(self):316 path =tkinter.Tk()317 path.withdraw()318 fpath =os.path.normpath(tkinter.filedialog.askdirectory())319 if fpath != ".":320 self.path.set(str(fpath))321
322 defmain():323 create_logger(level=logging.DEBUG)324 modify_string()325
326 if __name__ == '__main__':327 main()