1 # system module 2 import os 3 import re 4 import tkinter 5 import tkinter.messagebox 6 import tkinter.filedialog 7 import tkinter.ttk 8 import sys 9 import logging 10 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 if console_swtich: 30 console_handler = logging.StreamHandler(sys.stdout) 31 console_handler.formatter = formatter 32 logger.addHandler(console_handler) 33 34 # 指定日志的最低输出级别,默认为warn级别 35 logger.setLevel(level) 36 37 return logger 38 39 class modify_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 def menus(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 def layout(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 def matchcase(self, word): 179 return word 180 # 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 def modify(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 in filenames: 216 domain = os.path.abspath(path) 217 file_path = os.path.join(domain, filename) 218 219 # 递归修改子文件名称、文件名称、文件内容 220 if os.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} ") 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 while True: 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 def start(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 = 0 275 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 def log(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 def rule(self): 298 tkinter.messagebox.showinfo('批量修改字符串规则', 299 "1.修改当前文件夹及子文件夹的名称; " 300 "2.修改当前文件夹及子文件夹下所有文件的名称; " 301 "3.修改当前文件夹及子文件夹下所有文件的内容; ") 302 303 def about(self): 304 tkinter.messagebox.showinfo('批量修改字符串', 305 "作者:Risun_Lee " 306 "版本: V1.0 " 307 "发布日期: 2020年9月8日 ") 308 309 def release_note(self): 310 tkinter.messagebox.showinfo('版本说明', 311 "V1.0: " 312 "1.支持文件夹名称、文件名称的修改; " 313 "2.支持txt、c、h文件内容的修改; ") 314 315 def select_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 def main(): 323 create_logger(level=logging.DEBUG) 324 modify_string() 325 326 if __name__ == '__main__': 327 main()