在工作过程中,经常有很多文件,想要对文件名进行批量改名,特此写了一个程序,以实现此功能。
一、批量文件重命名软件设计原理
(一)核心原理阐述
批量文件重命名软件的核心原理在于运用操作系统提供的文件管理功能,借助编程手段达成对文件名称的批量修改。在这个软件里,我们采用 Python 的 Kivy 库来构建图形用户界面(GUI),同时利用 Python 的 os 和 shutil 库来处理文件操作。当用户选定特定文件夹后,软件会读取该文件夹下的所有文件,接着依据用户设定的重命名规则(像添加前缀、删除特定字符、编号排序等)对文件名进行修改,最后统一应用这些规则完成批量重命名操作。
该软件的工作流程可以概括为以下几个关键步骤:
- 用户交互阶段:通过 GUI 界面获取用户输入的重命名规则和目标文件夹
- 文件处理阶段:读取目标文件夹中的文件列表并解析文件名结构
- 规则应用阶段:根据用户设置的规则生成新的文件名
- 执行操作阶段:预览或实际执行重命名操作,并反馈结果
(二)关键技术剖析
1. Kivy 库的应用
Kivy 是一款功能强大的 Python 开源库,支持跨平台开发,能够在 Windows、Linux、macOS 等多种操作系统上运行。它采用现代的图形渲染引擎,支持硬件加速,能够创建流畅的用户界面。Kivy 的核心特点包括:
- Widget 体系:所有 UI 元素都是 Widget 的子类,支持嵌套和复合组件
- 布局管理器:提供多种布局方式(BoxLayout、GridLayout、FloatLayout 等)
- 事件系统:基于触摸的事件处理模型,支持多点触控
- 属性绑定:使用
bind
方法实现属性的自动同步更新 - 资源管理:支持字体、图片等资源的加载和管理
在本软件中,Kivy 主要用于构建用户界面,包括文件选择区域、重命名规则设置面板和文件列表显示等功能。
2. 文件操作技术
Python 的 os 库和 shutil 库提供了丰富的文件和目录操作功能:
- os.listdir():获取指定目录下的所有文件和文件夹列表
- os.path.splitext():分离文件名和扩展名
- os.rename():重命名文件或目录
- os.path.isfile():判断路径是否为文件
- shutil 库:提供高级文件操作,如复制、移动等(本软件主要使用 os.rename)
这些功能是实现批量文件重命名的基础,通过组合使用这些函数,软件能够高效地处理大量文件的重命名操作。
3. 正则表达式的使用
在处理复杂的文本替换需求时,正则表达式是一个非常有用的工具。Python 的 re 库提供了正则表达式功能,本软件中主要用于:
- 删除括号内编号:使用正则表达式
\(\d+\)
匹配类似 "(1)"、"(2)" 的编号并删除 - 自定义规则:在自定义重命名函数中可以使用正则表达式进行复杂的文本处理
正则表达式的使用使得软件能够处理各种复杂的文件名模式,提高了重命名规则的灵活性和强大性。
二、软件功能模块构成
(一)文件选择模块
该模块的主要功能是让用户能够选择要进行文件操作的目标文件夹。用户可以通过点击 "浏览" 按钮,在弹出的文件浏览器中选择所需的文件夹,软件会自动获取该文件夹的路径并显示在界面上。
核心功能包括:
- 打开系统文件选择对话框
- 递归设置文件选择器中的中文字体支持
- 处理用户选择的文件夹路径并更新 UI
(二)文件预览模块
文件预览模块会将用户所选文件夹中的所有文件以列表的形式展示出来。列表包含三个主要列:选择框、原文件名和新文件名(根据当前规则生成)。用户在进行重命名操作之前,能够清楚地看到当前文件夹下的文件情况以及重命名后的效果,为后续的重命名操作提供参考。
关键特性:
- 动态加载文件夹中的文件列表
- 实时显示原文件名和根据当前规则生成的新文件名
- 支持选择或取消选择单个文件
- 提供清晰的表头和分隔线,增强可读性
(三)重命名规则设定模块
此模块为用户提供了多种重命名规则选项,用户可以根据自己的需求进行选择和设置:
1. 添加前缀
用户可以输入想要添加的前缀内容,软件会将该前缀添加到每个文件名的前面。例如,输入前缀 "IMG_",则文件 "1.jpg" 将被重命名为 "IMG_1.jpg"。
2. 添加后缀
用户输入后缀内容后,软件会把后缀添加到每个文件名的后面。例如,输入后缀 "_backup",则文件 "1.jpg" 将被重命名为 "1_backup.jpg"。
3. 替换文本
用户可以指定要替换的字符和替换后的字符,软件会在所有文件名中查找并替换这些字符。例如,将空格替换为下划线,"photo 1.jpg" 将变为 "photo_1.jpg"。
4. 删除字符
用户输入要删除的字符,软件会将文件名中包含的这些字符删除。例如,删除 "_old",则 "photo_old.jpg" 将变为 "photo.jpg"。
5. 编号排序
软件会按照一定的顺序为文件添加编号,用户可以设置编号的起始值、步长等参数。例如,起始值为 1,步长为 1,位数为 3,则文件名将添加 "001_"、"002_" 等前缀。
6. 删除括号内编号
这是一个特殊的删除功能,使用正则表达式匹配并删除类似 "(1)"、"(2)" 的编号,例如 "文件 (1).txt" 将变为 "文件.txt"。
7. 修改后缀
用户可以选择是否修改文件的后缀名,并指定新的后缀名,软件会对所有文件的后缀进行相应的修改。
8. 自定义规则
对于有特殊需求的用户,可以通过编写自定义的 Python 代码来实现独特的重命名规则。自定义函数需要接收文件名和扩展名作为参数,并返回新的文件名。
(四)操作执行模块
操作执行模块主要负责执行用户设定的重命名操作:
- 预览功能:在实际执行重命名前,显示重命名后的效果,让用户确认
- 确认对话框:执行前再次向用户确认操作信息,避免误操作
- 进度显示:执行过程中显示操作进度,让用户了解当前状态
- 结果反馈:操作完成后,显示成功和失败的统计信息及详细错误
三、代码详细解析
(一)整体架构
整个软件的代码结构清晰,采用了面向对象的设计思想,主要由以下几个部分组成:
- 字体设置模块:
setup_fonts
函数负责设置中文字体支持 - 主应用类:
FileRenameApp
类继承自 Kivy 的 App 类,是整个应用的核心 - 界面布局方法:负责创建和管理 UI 界面
- 文件操作方法:处理文件选择、加载和显示
- 重命名规则方法:根据用户设置生成新文件名
- 操作执行方法:处理预览和实际重命名操作
- 辅助方法:提供对话框显示、文件选择等辅助功能
以下是完整的代码:
import os
import re
import shutil
from datetime import datetime
from kivy.app import App
from kivy.clock import Clock
from kivy.core.text import LabelBase
from kivy.core.window import Window
from kivy.resources import resource_add_path, resource_find
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.checkbox import CheckBox
from kivy.uix.filechooser import FileChooserListView
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.popup import Popup
from kivy.uix.progressbar import ProgressBar
from kivy.uix.scrollview import ScrollView
from kivy.uix.textinput import TextInput
from kivy.uix.togglebutton import ToggleButton
from kivy.uix.tabbedpanel import TabbedPanel, TabbedPanelItem
from kivy.uix.spinner import Spinner
from kivy.uix.slider import Slider
from kivy.uix.image import Image
from kivy.graphics import Color, Rectangle
# 确保中文显示的字体处理
def setup_fonts():
"""设置中文字体支持"""
font_name = "NotoSansCJK"
# 尝试查找系统中的Noto Sans CJK字体
system_fonts = [
"/System/Library/Fonts/PingFang.ttc", # macOS
"/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc", # Linux
"C:/Windows/Fonts/NotoSansCJK-Regular.ttc", # Windows
"C:/Windows/Fonts/simhei.ttf", # Windows 备用
"C:/Windows/Fonts/simsun.ttc", # Windows 宋体
]
font_path = None
for path in system_fonts:
if os.path.exists(path):
font_path = path
break
# 如果找不到系统字体,则使用相对路径(假设字体文件在应用目录中)
if not font_path:
font_path = resource_find("NotoSansCJK-Regular.ttc")
if not font_path:
print("警告: 未找到Noto Sans CJK字体,中文可能无法正确显示")
return None
# 注册字体
try:
LabelBase.register(name=font_name, fn_regular=font_path)
return font_name
except Exception as e:
print(f"字体注册失败: {e}")
return None
# 设置中文字体
chinese_font = setup_fonts()
if not chinese_font:
chinese_font = "Roboto" # 默认回退字体
class FileRenameApp(App):
def build(self):
# 设置窗口标题和大小
Window.size = (900, 600)
self.title = '批量文件重命名工具'
# 创建主布局
main_layout = BoxLayout(orientation='vertical', padding=10, spacing=10)
# 创建顶部的文件选择区域
file_select_layout = BoxLayout(orientation='horizontal', size_hint=(1, 0.1))
self.file_path_input = TextInput(
multiline=False,
hint_text='请选择文件夹',
font_name=chinese_font,
font_size=14 # 设置字体大小
)
browse_button = Button(
text='浏览...',
size_hint=(0.2, 1),
font_name=chinese_font,
font_size=14 # 设置字体大小
)
browse_button.bind(on_press=self.browse_folder)
file_select_layout.add_widget(self.file_path_input)
file_select_layout.add_widget(browse_button)
# 创建标签页面板
self.tab_panel = TabbedPanel(do_default_tab=False, size_hint=(1, 0.7))
# 文件列表标签页
files_tab = TabbedPanelItem(
text='文件列表',
font_name=chinese_font,
font_size=14 # 设置标签页字体大小
)
self.file_list_layout = GridLayout(cols=1, spacing=5, size_hint_y=None)
self.file_list_layout.bind(minimum_height=self.file_list_layout.setter('height'))
scroll_view = ScrollView()
scroll_view.add_widget(self.file_list_layout)
files_tab.add_widget(scroll_view)
# 重命名规则标签页
rules_tab = TabbedPanelItem(
text='重命名规则',
font_name=chinese_font,
font_size=14 # 设置标签页字体大小
)
# 将规则布局放在ScrollView中,确保内容可滚动
rules_scroll_view = ScrollView(size_hint=(1, 1), size=(2000, 400))
self.rules_layout = self.create_rules_layout()
rules_scroll_view.add_widget(self.rules_layout)
rules_tab.add_widget(rules_scroll_view)
# 添加标签页到面板
self.tab_panel.add_widget(files_tab)
self.tab_panel.add_widget(rules_tab)
# 创建底部的操作按钮区域
action_layout = BoxLayout(orientation='horizontal', size_hint=(1, 0.1), spacing=10)
preview_button = Button(
text='预览重命名',
size_hint=(0.3, 1),
font_name=chinese_font,
font_size=14 # 设置字体大小
)
preview_button.bind(on_press=self.preview_rename)
execute_button = Button(
text='执行重命名',
size_hint=(0.3, 1),
font_name=chinese_font,
font_size=14 # 设置字体大小
)
execute_button.bind(on_press=self.execute_rename)
clear_button = Button(
text='清空列表',
size_hint=(0.3, 1),
font_name=chinese_font,
font_size=14 # 设置字体大小
)
clear_button.bind(on_press=self.clear_files)
action_layout.add_widget(preview_button)
action_layout.add_widget(execute_button)
action_layout.add_widget(clear_button)
# 添加所有组件到主布局
main_layout.add_widget(file_select_layout)
main_layout.add_widget(self.tab_panel)
main_layout.add_widget(action_layout)
# 存储文件信息的列表
self.files = []
self.original_files = []
return main_layout
def create_rules_layout(self):
"""创建重命名规则设置界面"""
# 创建一个垂直布局(主布局)
rules_layout = BoxLayout(orientation='vertical', spacing=15, padding=10, size_hint_y=None)
rules_layout.bind(minimum_height=rules_layout.setter('height'))
# 添加前缀设置区域
prefix_section = self.create_setting_section("添加前缀")
prefix_layout = BoxLayout(orientation='horizontal', spacing=10, size_hint_y=None, height=40)
self.prefix_checkbox = CheckBox(active=False, size_hint=(0.1, 1))
self.prefix_text = TextInput(
multiline=False,
disabled=True,
font_name=chinese_font,
font_size=14,
size_hint=(0.9, 1),
hint_text='请输入前缀'
)
self.prefix_checkbox.bind(active=lambda instance, value: self.prefix_text.set_disabled(not value))
prefix_layout.add_widget(self.prefix_checkbox)
prefix_layout.add_widget(self.prefix_text)
prefix_section.add_widget(prefix_layout)
rules_layout.add_widget(prefix_section)
# 添加后缀设置区域
suffix_section = self.create_setting_section("添加后缀")
suffix_layout = BoxLayout(orientation='horizontal', spacing=10, size_hint_y=None, height=40)
self.suffix_checkbox = CheckBox(active=False, size_hint=(0.1, 1))
self.suffix_