'''python写代码,tkinter实现UI用户交互界面,导入xml.etree.ElementTree模块解析xml格式文件。
功能:
用户单击“浏览”执行browse_folder_path()函数,打开文件夹,
用户输入待查找字符串(用户单选框Checkbutton选择是否大小写敏感),
用户输入字符串重复出现的次数(用户单选框Combobox选择:等于,大于,小于),
用户输入替换字符串或中文字符,
用户单击“开始查找”执行search_files()函数,遍历文件夹和子文件夹内所有.txt和.xml格式文件,如果出现xml文件内容格式不正确,跳过该文件。
将查找结果返回显示,如果没有符合的结果,显示“搜索无果!”
用户单击“开始替换”执行replace_files()函数,询问用户:直接替换,另存为。将search_files()函数查找的结果进行字符串替换。
注意使用中文表达,不要写注释'''
import os
import tkinter as tk
from tkinter import filedialog
from tkinter import messagebox
from tkinter import ttk
import xml.etree.ElementTree as ET
import markdown
selected_filetypes = []
folder_path = ''
#---
# folder_dir = ''
# search_string = ''
# case_sensitive = ''
# search_count = 1
# search_type = ''
# replace_string = ''
#----
def browse_folder_path():
global folder_path
folder_selected = filedialog.askdirectory()
folder_path.set(folder_selected)
def search_files():
folder_dir = folder_path.get()
search_string = search_string_entry.get()
case_sensitive = case_sensitive_var.get()
search_count = int(search_count_entry.get())
search_type = search_type_var.get()
global selected_filetypes
if not os.path.isdir(folder_dir):
messagebox.showerror("错误", "文件夹路径无效")
return
search_results.delete(1.0, tk.END) # 清空文本框
if xml_var.get():
selected_filetypes.append('.xml')
if txt_var.get():
selected_filetypes.append('.txt')
if py_var.get():
selected_filetypes.append('.py')
if yaml_var.get():
selected_filetypes.append('.yaml')
if md_var.get():
selected_filetypes.append('.md')
found_files = []
for root, dirs, files in os.walk(folder_dir):
for file in files:
file_ext = os.path.splitext(file)[1].lower() # 获取文件的后缀并转为小写
# 另一种写法:if file.endswith(('.txt', '.xml')):括号内用tuple()元组
if file_ext in selected_filetypes:
file_path = os.path.join(root, file) # file_path形如input.yaml,也就是文件名
text = ""
if file_ext == '.xml':
with open(file_path, 'r', encoding='utf-8') as xml_file:
tree = ET.parse(xml_file)
root_element = tree.getroot()
for element in root_element.iter():
text += element.text + " "
# element.text = ET.tostring(root, encoding='utf-8').decode() # todo
elif file_ext == '.txt':
with open(file_path, 'r', encoding='utf-8', errors='ignore') as txt_file:
text = txt_file.read()
elif file_ext == '.py':
with open(file_path, 'r', encoding='utf-8', errors='ignore') as py_file:
text = py_file.read()
elif file_ext == '.yaml':
with open(file_path, 'r', encoding='utf-8', errors='ignore') as yaml_file:
# yaml_data = yaml.load(yaml_file, Loader=yaml.FullLoader)
# text = yaml.dump(yaml_data)
text = yaml_file.read()
elif file_ext == '.md':
with open(file_path, 'r', encoding='utf-8', errors='ignore') as md_file:
text = md_file.read()
text = markdown.markdown(text)
if not case_sensitive:
text = text.lower()
search_string = search_string.lower()
count = text.count(search_string)
if (search_type == "=" and count == search_count) or \
(search_type == ">" and count > search_count) or \
(search_type == "<" and count < search_count):
found_files.append(file_path)
if found_files:
search_results.insert(tk.END, "找到以下文件匹配搜索条件:\n")
for file_path in found_files:
search_results.insert(tk.END, file_path + "\n")
search_results.insert(tk.END, "\n")
else:
search_results.insert(tk.END, "搜索无果!\n")
replace_button.config(state=tk.NORMAL)
def replace_files():
folder_dir = folder_path.get()
search_string = search_string_entry.get()
case_sensitive = case_sensitive_var.get()
replace_string = replace_string_entry.get()
if not os.path.isdir(folder_dir):
messagebox.showerror("错误", "文件夹路径无效")
return
for root, dirs, files in os.walk(folder_dir):
for file in files:
file_ext = os.path.splitext(file)[1].lower()
if file_ext in selected_filetypes:
file_path = os.path.join(root, file)
text = ""
# if file_ext == '.xml':
# tree = ET.parse(file_path)
# root = tree.getroot()
# text = ET.tostring(root, encoding='utf-8').decode()#字符串转中文utf-8编码
if file_ext == '.xml':
with open(file_path, 'r', encoding='utf-8') as xml_file:
tree = ET.parse(xml_file)
root_element = tree.getroot()
for element in root_element.iter():
text += element.text + " "
# element.text = ET.tostring(root, encoding='utf-8').decode() # todo
elif file_ext == '.txt':
with open(file_path, 'r', encoding='utf-8', errors='ignore') as txt_file:
text = txt_file.read()
elif file_ext == '.py':
with open(file_path, 'r', encoding='utf-8', errors='ignore') as py_file:
text = py_file.read()
elif file_ext == '.yaml':
with open(file_path, 'r', encoding='utf-8', errors='ignore') as yaml_file:
# yaml_data = yaml.load(yaml_file, Loader=yaml.FullLoader)#todo
# text = yaml.dump(yaml_data)
text = yaml_file.read()
elif file_ext == '.md':
with open(file_path, 'r', encoding='utf-8', errors='ignore') as md_file:
text = md_file.read()
text = markdown.markdown(text)
if not case_sensitive:
text = text.lower()
search_string = search_string.lower()
new_text = text.replace(search_string, replace_string)
if file_ext == '.xml':
with open(file_path, 'r', encoding='utf-8', errors='ignore') as xml_file:
tree = ET.parse(xml_file)
root_element = tree.getroot()
for element in root_element.iter():
if search_string in element.text:
element.text = element.text.replace(search_string, replace_string)
tree.write(file_path, encoding='utf-8') # todo encoding='utf-8'表明写入的编码格式为中文
elif file_ext == '.txt':
with open(file_path, 'w', encoding='utf-8', errors='ignore') as new_txt_file:
new_txt_file.write(new_text)
elif file_ext == '.py':
with open(file_path, 'w', encoding='utf-8', errors='ignore') as new_py_file:
new_py_file.write(new_text)
elif file_ext == '.yaml':
with open(file_path, 'w', encoding='utf-8', errors='ignore') as new_yaml_file:
new_yaml_file.write(new_text)
elif file_ext == '.md':
with open(file_path, 'w', encoding='utf-8', errors='ignore') as new_md_file:
new_md_file.write(new_text)
search_results.insert(tk.END, "替换完成\n")
def reset():
folder_entry.delete(0,'end')
search_count_entry.delete(0,'end')
replace_string_entry.delete(0, 'end')
search_string_entry.delete(0, 'end')
# 创建主窗口
root = tk.Tk()
root.iconbitmap(r'F:\kdy.ico')
root.title("文件查找和替换工具v1.0 by zsp")
# grid默认居中排布,w表示左对齐,e表示右对齐,sticky=N+W+W+E 拉高并拉长组件,让组件填充满一个表格框。
# 文件夹路径变量
folder_path = tk.StringVar()
# 创建文件夹选择按钮和输入框
folder_label = tk.Label(root, text="选择文件夹:")
folder_label.grid(row=0, column=0, sticky="e")
folder_entry = tk.Entry(root, width=20, textvariable=folder_path)
folder_entry.grid(row=0, column=1)
folder_button = tk.Button(root, text="浏览", fg='#CD70FF', command=browse_folder_path)
folder_button.grid(row=0, column=2, sticky="w")
# 创建搜索字符串输入框
search_string_label = tk.Label(root, text="查找字符串:")
search_string_label.grid(row=1, column=0, sticky="e")
search_string_entry = tk.Entry(root, width=20)
search_string_entry.grid(row=1, column=1)
# 创建大小写敏感选择框
case_sensitive_var = tk.BooleanVar()
case_sensitive_checkbox = tk.Checkbutton(root, text="Aa", variable=case_sensitive_var)
case_sensitive_checkbox.grid(row=1, column=2, sticky="w")
# 创建搜索次数和类型输入框,初始化值1
num = tk.StringVar(value=1)
search_count_label = tk.Label(root, text="重复次数:")
search_count_label.grid(row=2, column=0, sticky="e")
search_count_entry = tk.Entry(root, width=20, textvariable=num)
search_count_entry.grid(row=2, column=1)
search_type_var = tk.StringVar()
search_type_combobox = ttk.Combobox(root, width=3, textvariable=search_type_var, values=["=", ">", "<"])
search_type_combobox.set("=")
search_type_combobox.grid(row=2, column=2, sticky="w")
# 创建替换字符串输入框
replace_string_label = tk.Label(root, text="替换字符串:")
replace_string_label.grid(row=3, column=0, sticky="e")
replace_string_entry = tk.Entry(root, width=20)
replace_string_entry.grid(row=3, column=1)
# 创建搜索结果文本框
search_results = tk.Text(root, width=60, height=10)
search_results.grid(row=5, column=0, columnspan=3, sticky="e")
# LabelFrame标签框架
labelFrame = tk.LabelFrame(root, text="文件类型")
labelFrame.grid(row=4, column=0, columnspan=3)
# 创建复选框来选择文件类型
md_var = tk.BooleanVar()
md_checkbox = tk.Checkbutton(labelFrame, text=".md", variable=md_var)
md_checkbox.grid(row=0, column=0, sticky="w")
py_var = tk.BooleanVar()
py_checkbox = tk.Checkbutton(labelFrame, text=".py", variable=py_var)
py_checkbox.grid(row=0, column=1, sticky="w")
txt_var = tk.BooleanVar()
txt_checkbox = tk.Checkbutton(labelFrame, text=".txt", variable=txt_var)
txt_checkbox.grid(row=0, column=2, sticky="w")
xml_var = tk.BooleanVar()
xml_checkbox = tk.Checkbutton(labelFrame, text=".xml", variable=xml_var)
xml_checkbox.grid(row=0, column=3, sticky="w")
yaml_var = tk.BooleanVar()
yaml_checkbox = tk.Checkbutton(labelFrame, text=".yaml", variable=yaml_var)
yaml_checkbox.grid(row=0, column=4, sticky="w")
# 创建开始查找按钮
search_button = tk.Button(root, text="开始查找", font=('times', 12, 'bold'), fg='#00ff00', command=search_files)
search_button.grid(row=6, column=0, pady=10, sticky='NSEW')
# 创建开始替换按钮
replace_button = tk.Button(root, text="开始替换", font=('times', 12, 'bold'), fg='#ff0000', command=replace_files,
state=tk.DISABLED)
replace_button.grid(row=6, column=1, pady=10, sticky='NSEW')
# 创建开始清除按钮
reset_button = tk.Button(root, text="清除", font=('times', 12, 'bold'), fg='#0000ff', command=reset)
reset_button.grid(row=6, column=2, pady=10, sticky='NSEW')
# 启动主循环
root.mainloop()
效果
尚且不支持doc,pdf之类的格式