<think>我们修改重命名的格式,要求:
1. 如果文件夹中只有图片(即视频数为0),则显示为 [图片数量p ?M] 其中M表示兆字节(MB),保留两位小数。
2. 如果文件夹中只有视频(即图片数为0),则显示为 [视频数量v ?G] 其中G表示吉字节(GB),保留两位小数。
3. 如果两者都有,则显示为 [图片数量p 视频数量v ?G] 其中G表示吉字节(GB),保留两位小数。
注意:我们不再使用总文件数(图片+视频)作为p的数值,而是分开显示图片和视频的数量。
同时,对于大小:
- 如果总大小小于1GB,则用MB表示,并保留两位小数。
- 如果大于等于1GB,则用GB表示,并保留两位小数。
另外,我们不需要显示总文件数(即不再使用总文件数p,而是分别显示图片和视频的数量)。
因此,新名称格式为:
- 纯图片文件夹: "原文件夹名 [23p 0.17M]" (注意:这里0.17是MB,但实际计算时,如果总大小小于1GB,我们就用MB表示,否则用GB)
- 纯视频文件夹: "原文件夹名 [5v 1.25G]"
- 混合文件夹: "原文件夹名 [23p 5v 1.25G]"
但是注意:在混合文件夹中,如果总大小小于1GB,我们也要用MB?但是原要求是混合文件夹用G(因为视频通常比较大)。不过为了统一,我们按照以下规则:
- 如果总大小小于1024MB(即1GB),则用MB表示(保留两位小数),并加上M
- 如果大于等于1024MB,则用GB表示(保留两位小数),并加上G
所以,在重命名时,我们需要根据总字节数判断使用哪个单位。
修改步骤:
1. 在分析文件夹时,计算总大小(字节)
2. 根据总大小决定单位:
total_size_bytes = ... # 总字节数
if total_size_bytes < 1024 * 1024 * 1024:
size_str = f"{total_size_bytes / (1024*1024):.2f}M"
else:
size_str = f"{total_size_bytes / (1024*1024*1024):.2f}G"
3. 根据图片和视频的数量构建字符串:
if video_count == 0 and image_count > 0: # # 只有图片
tag = f"[{image_count}p {size_str}]"
elif image_count == 0 and video_count > 0: # 只有视频
tag = f"[{video_count}v {size_str}]"
else: # 两者都有
tag = f"[{image_count}p {video_count}v {size_str}]"
4. 注意:原文件夹名中可能已经包含类似标签,需要先去除。
另外,原要求是:对于这种[23p 0v 0.17G]不需要,改成 [23p ?M]
所以,我们上面的逻辑已经避免了显示0v的情况(因为纯图片时,我们不会显示视频数)。
但是,注意:如果文件夹中既有图片又有视频,但视频数量为0?这实际上不会发生,因为视频为0的话,我们就按纯图片处理了。
因此,我们修改analyze_folder函数中生成new_name的部分。
同时,我们还要注意:如果文件夹中既没有图片也没有视频,那么就不应该重命名(should_rename为false),因为other_count>0,所以不会重命名。
修改代码部分:
原代码:
base_name = re.sub(r'\s*\[\d+p\s+\d+v\s+\d+\.\d+G\]$', '', folder_name).strip()
new_name = f"{base_name} [{video_count+image_count}p {video_count}v {size_gb:.2f}G]"
改为:
base_name = re.sub(r'\s*\[\d+p(?:\s+\d+v)?\s+\d+(?:\.\d+)?[MG]\]\s*$', '', folder_name).strip()
# 计算大小字符串
if total_size < 1024**3: # 小于1GB,用MB
size_str = f"{total_size / (1024**2):.2f}M" # 转换为MB
else:
size_str = f"{total_size / (1024**3):.2f}G" # 转换为GB
if video_count == 0 and image_count > 0:
tag = f"[{image_count}p {size_str}]"
elif image_count == 0 and video_count > 0:
tag = f"[{video_count}v {size_str}]"
else:
tag = f"[{image_count}p {video_count}v {size_str}]"
new_name = f"{base_name} {tag}"
注意:我们使用正则表达式去除旧标签时,需要匹配多种格式(比如纯图片、纯视频、混合),所以正则表达式改为:
r'\s*\[\d+p(?:\s+\d+v)?\s+\d+(?:\.\d+)?[MG]\]\s*$'
解释:
\s* # 空白
\[ # 左括号
\d+p # 数字+p
(?:\s+\d+v)? # 可选部分:空白+数字+v
\s+ # 空白
\d+(?:\.\d+)? # 数字(整数或小数)
[MG] # M或G
\] # 右括号
\s*$ # 结尾空白
但是注意:这个正则可能不够精确,因为大小部分可能是整数也可能是小数,而且可能有空格变化。我们也可以考虑更简单的:去除所有以[...]结尾的标签(但这样可能误伤)。或者我们可以分两步:先去除旧格式的标签(我们之前生成的格式),再去除新格式的标签?但为了简单,我们用一个正则匹配新旧格式。
不过,我们之前生成的格式是固定的,所以我们可以考虑匹配多种情况。
另外,注意如果用户手动添加了其他标签,我们可能不想去除。但根据需求,我们只去除我们自己生成的标签。所以,我们只匹配我们生成的格式。
我们生成的格式有三种:
[23p 0.17M]
[5v 1.25G]
[23p 5v 1.25G]
所以,我们可以写三个正则?或者一个正则匹配这三种?
我们可以这样写:
pattern = r'\s*\[\d+p(?:\s+\d+v)?\s+\d+(?:\.\d+)?[MG]\]\s*$'
这个正则可以匹配:
[数字p 数字M] -> 匹配纯图片
[数字v 数字G] -> 匹配纯视频(但注意这里我们用了p和v,而纯视频是v,所以需要调整)
调整:因为纯视频的是以v开头,所以我们不能强制要求以p开头。所以我们需要更灵活的正则。
我们可以写成:
pattern = r'\s*\[(\d+p\s+)?(\d+v\s+)?\d+(?:\.\d+)?[MG]\]\s*$'
但是这样可能匹配到不完整的标签。所以,我们改为:
pattern = r'\s*\[(\d+p)?\s*(\d+v)?\s*[\d.]+\s*[MG]\]\s*$'
但这样可能匹配到非我们生成的标签。为了安全,我们只匹配我们自己的格式,即要求标签中必须包含单位M或G,并且前面是数字。
我们重新设计正则:
pattern = r'\s*\[\s*(\d+\s*p)?\s*(\d+\s*v)?\s*[\d.]+\s*[MG]\s*\]\s*$'
但是这样可能会匹配到:
[p 3v 10M] -> 我们不希望这样
所以,我们要求数字必须和字母紧挨着:
pattern = r'\s*\[\s*(\d+p\s+)?(\d+v\s+)?[\d.]+\s*[MG]\]\s*$'
测试:
[23p 0.17M] -> 匹配:23p后面有空格,然后0.17M
[5v 1.25G] -> 匹配:5v后面有空格,然后1.25G
[23p 5v 1.25G] -> 匹配:23p空格,5v空格,然后1.25G
但是注意,我们的新格式中,纯图片的标签是[23p 0.17M],所以这个正则可以匹配。
但是,如果数字和单位之间没有空格呢?比如[23p0.17M]?我们生成的时候是有空格的,所以不考虑。
因此,我们使用:
base_name = re.sub(r'\s*\[\s*(\d+p\s+)?(\d+v\s+)?\d+(?:\.\d+)?\s*[MG]\]\s*$', '', folder_name).strip()
注意:这里我们允许数字部分可能是整数或小数,并且单位M或G前可能有空格(但生成的时候有空格,所以这里允许空格)。
另外,为了避免匹配到不完整的标签(比如只有单位),我们要求至少有一个数字部分(比如23p或5v)和大小部分。
但是,如果纯视频的标签[5v 1.25G],那么正则匹配时,第一组是None(因为没有p的部分),第二组匹配到5v,然后匹配大小部分。
所以,这个正则可以匹配三种情况。
但是,如果文件夹名中包含了多个标签,这个正则只会匹配最后一个标签(因为$表示结尾)。所以,我们只去除最后一个标签。
修改代码:
# 去除旧标签(我们生成的)
base_name = re.sub(r'\s*\[\s*(\d+p\s+)?(\d+v\s+)?\d+(?:\.\d+)?\s*[MG]\]\s*$', '', folder_name).strip()
然后,构建新标签。
最后,将新名称设置为:base_name + 空格 + 新标签
注意:如果base_name为空,则直接使用新标签(但这种情况很少)。
我们修改analyze_folder函数中的相关部分。
另外,注意:如果文件夹中既有图片又有视频,但是视频数量为0?这种情况我们按纯图片处理。同样,图片数量为0按纯视频处理。
所以,在生成标签时,我们这样判断:
if video_count == 0 and image_count > 0:
# 只有图片
tag = f"[{image_count}p {size_str}]"
elif image_count == 0 and video_count > 0:
# 只有视频
tag = f"[{video_count}v {size_str}]"
else:
# 混合(注意:可能两者都0?但这种情况不会重命名,因为other_count>0,所以should_rename为false,所以这里不用考虑两者为0的情况)
tag = f"[{image_count}p {video_count}v {size_str}]"
但是,如果两者都为0,那么就不会进入重命名,所以没关系。
修改后的analyze_folder函数代码段:
# 计算大小字符串
if total_size < 1024**3: # 小于1GB,用MB
size_str = f"{total_size / (1024**2):.2f}M" # 转换为MB
else:
size_str = f"{total_size / (1024**3):.2f}G" # 转换为GB
# 去除旧标签(匹配我们之前生成的格式)
base_name = re.sub(r'\s*\[\s*(\d+p\s+)?(\d+v\s+)?\d+(?:\.\d+)?\s*[MG]\]\s*$', '', folder_name).strip()
# 构建新标签
if video_count == 0 and image_count > 0:
tag = f"[{image_count}p {size_str}]"
elif image_count == 0 and video_count > 0:
tag = f"[{video_count}v {size_str}]"
else:
tag = f"[{image_count}p {video_count}v {size_str}]"
new_name = f"{base_name} {tag}"
注意:我们使用total_size(总字节数)来计算。
另外,在正则表达式中,我们匹配的是数字(整数或小数)后面紧跟一个空格和M或G,但实际生成时我们是没有空格在单位和数字之间的(比如0.17M),所以正则中的空格在数字和单位之间是可选的(\s*)。所以正则表达式可以匹配没有空格的情况,但我们的生成是带一个空格的(因为我们在size_str中就是数字和单位紧挨着)。所以,我们生成的新标签中,数字和单位之间没有空格(如0.17M),所以正则表达式要允许没有空格的情况。
因此,正则表达式中的单位前允许空格(\s*),但实际上我们生成的是没有空格的,所以匹配没有问题。
但是,我们生成的新标签中,在数字和单位之间没有空格,所以正则表达式要匹配这种格式,我们在正则中写的是`\d+(?:\.\d+)?\s*[MG]`,所以可以匹配没有空格的情况。
现在,我们修改代码,替换原来的analyze_folder函数中的生成新名称的部分。
完整修改后的analyze_folder函数:
def analyze_folder(self, folder_path, folder_name):
"""分析文件夹内容并返回统计信息"""
video_count = 0
image_count = 0
other_count = 0
total_size = 0
# 遍历文件夹中的所有文件
for root, dirs, files in os.walk(folder_path):
for file in files:
if not self.running:
break
file_path = os.path.join(root, file)
file_ext = os.path.splitext(file)[1].lower()
# 检查文件类型
if file_ext in VIDEO_EXTENSIONS:
video_count += 1
elif file_ext in IMAGE_EXTENSIONS:
image_count += 1
else:
other_count += 1
# 计算文件大小
try:
total_size += os.path.getsize(file_path)
except:
pass
# 确定是否需要重命名(仅包含视频/图片文件)
should_rename = other_count == 0
# 计算大小字符串
if total_size < 1024**3: # 小于1GB,用MB
size_str = f"{total_size / (1024**2):.2f}M" # 转换为MB
else:
size_str = f"{total_size / (1024**3):.2f}G" # 转换为GB
# 去除旧标签(匹配我们之前生成的格式)
base_name = re.sub(r'\s*\[\s*(\d+p\s+)?(\d+v\s+)?\d+(?:\.\d+)?\s*[MG]\]\s*$', '', folder_name).strip()
# 构建新标签
if video_count == 0 and image_count > 0:
tag = f"[{image_count}p {size_str}]"
elif image_count == 0 and video_count > 0:
tag = f"[{video_count}v {size_str}]"
else:
tag = f"[{image_count}p {video_count}v {size_str}]"
new_name = f"{base_name} {tag}"
return {
'path': folder_path,
'original_name': folder_name,
'video_count': video_count,
'image_count': image_count,
'other_count': other_count,
'total_size': total_size,
'should_rename': should_rename,
'new_name': new_name
}
注意:我们返回的字典中不再需要'size_gb',但为了保持结构,我们可以保留,也可以去掉。这里我们去掉,因为已经不需要了。
但是,为了在日志中显示总大小,我们之前使用了self.format_size(total_size),现在在日志中我们直接使用size_str(但日志中显示的是我们计算后的字符串,所以不需要修改日志函数,因为日志函数是独立使用format_size的)。
但是,在日志中我们显示的是:
self.log(f" 视频文件: {stats['video_count']}个, 图片文件: {stats['image_count']}个")
self.log(f" 总大小: {self.format_size(stats['total_size'])}")
所以,日志中显示的大小是独立的,不受影响。
因此,我们只需要修改生成新名称的部分。
最后,我们还需要注意:如果文件夹名在去除旧标签后变成了空字符串,那么新名称就变成了" [标签]",这样不好。所以,我们可以考虑如果base_name为空,则使用原文件夹名(不进行去除操作)?但这种情况很少,我们暂时不考虑。
另外,如果用户不想去除旧标签,我们也可以提供选项?但当前需求没有,所以不实现。
现在,修改后的代码应该可以满足要求。
但是,注意:我们生成的新标签中,在数字和单位之间没有空格(如0.17M),而正则表达式在匹配旧标签时允许空格,所以不会匹配到新标签(因为我们生成的新标签没有空格,但正则表达式中的`\s*`可以匹配0个空格)。所以,当重复运行程序时,新标签会被当作旧标签去除,然后添加新的标签。这样就会更新标签。
这样符合预期。
因此,我们只需要替换analyze_folder函数中的相关部分即可。
注意:正则表达式可能会匹配到一些非我们生成的标签(如果用户自己用了类似的格式),但风险较低。
我们修改代码后,重新运行程序测试。
由于整个程序较长,这里只提供修改后的关键函数。如果需要,可以替换原程序中的analyze_folder函数。
另外,原程序中的format_size函数仍然保留,用于日志中的大小显示(独立于重命名的大小字符串生成)。
下面,我们提供完整的修改后的代码(只修改了analyze_folder函数,其他不变):</think># 文件夹媒体文件统计与重命名工具(改进版)
我将修改之前的代码,按照您的要求调整重命名格式。主要改进是:
1. 对于纯图片文件夹,显示为 `[图片数量p 大小M]`(如 `[23p 0.17M]`)
2. 对于纯视频文件夹,显示为 `[视频数量v 大小G]`
3. 对于混合文件夹,显示为 `[图片数量p 视频数量v 大小G]`
以下是完整的改进代码:
```python
import os
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
import re
import threading
import subprocess
# 支持的视频和图片文件扩展名
VIDEO_EXTENSIONS = {'.mp4', '.avi', '.mkv', '.mov', '.wmv', '.flv', '.mpeg', '.mpg', '.ts', '.m4v', '.webm'}
IMAGE_EXTENSIONS = {'.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff', '.webp', '.svg'}
class FolderAnalyzerApp:
def __init__(self, root):
self.root = root
self.root.title("文件夹媒体文件统计工具")
self.root.geometry("800x600")
self.root.resizable(True, True)
# 设置应用图标
try:
self.root.iconbitmap("folder_icon.ico") # 如果有图标文件
except:
pass
# 创建UI框架
self.create_widgets()
# 存储分析结果
self.folder_stats = []
self.running = False
def create_widgets(self):
# 创建主框架
main_frame = ttk.Frame(self.root, padding=10)
main_frame.pack(fill=tk.BOTH, expand=True)
# 路径选择部分
path_frame = ttk.LabelFrame(main_frame, text="选择文件夹路径", padding=10)
path_frame.pack(fill=tk.X, pady=5)
self.path_var = tk.StringVar()
path_entry = ttk.Entry(path_frame, textvariable=self.path_var, width=60)
path_entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=(0, 5))
browse_btn = ttk.Button(path_frame, text="浏览...", command=self.browse_folder)
browse_btn.pack(side=tk.RIGHT)
# 选项部分
options_frame = ttk.Frame(main_frame)
options_frame.pack(fill=tk.X, pady=5)
self.rename_var = tk.BooleanVar(value=True)
rename_cb = ttk.Checkbutton(options_frame, text="自动重命名文件夹", variable=self.rename_var)
rename_cb.pack(side=tk.LEFT, padx=5)
self.preview_var = tk.BooleanVar(value=True)
preview_cb = ttk.Checkbutton(options_frame, text="预览重命名结果", variable=self.preview_var)
preview_cb.pack(side=tk.LEFT, padx=5)
# 进度条
self.progress_var = tk.DoubleVar()
progress_bar = ttk.Progressbar(main_frame, variable=self.progress_var, maximum=100)
progress_bar.pack(fill=tk.X, pady=10)
# 日志输出
log_frame = ttk.LabelFrame(main_frame, text="操作日志", padding=10)
log_frame.pack(fill=tk.BOTH, expand=True, pady=5)
self.log_text = tk.Text(log_frame, height=15, state=tk.DISABLED)
self.log_text.pack(fill=tk.BOTH, expand=True)
scrollbar = ttk.Scrollbar(log_frame, command=self.log_text.yview)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
self.log_text.config(yscrollcommand=scrollbar.set)
# 按钮区域
button_frame = ttk.Frame(main_frame)
button_frame.pack(fill=tk.X, pady=10)
self.analyze_btn = ttk.Button(button_frame, text="开始分析", command=self.start_analysis)
self.analyze_btn.pack(side=tk.LEFT, padx=5)
self.stop_btn = ttk.Button(button_frame, text="停止", command=self.stop_analysis, state=tk.DISABLED)
self.stop_btn.pack(side=tk.LEFT, padx=5)
self.open_btn = ttk.Button(button_frame, text="打开文件夹", command=self.open_folder, state=tk.DISABLED)
self.open_btn.pack(side=tk.RIGHT, padx=5)
# 状态栏
self.status_var = tk.StringVar(value="就绪")
status_bar = ttk.Label(self.root, textvariable=self.status_var, relief=tk.SUNKEN, anchor=tk.W)
status_bar.pack(side=tk.BOTTOM, fill=tk.X)
def browse_folder(self):
folder_path = filedialog.askdirectory(title="选择要分析的文件夹")
if folder_path:
self.path_var.set(folder_path)
def start_analysis(self):
path = self.path_var.get()
if not path or not os.path.isdir(path):
messagebox.showerror("错误", "请选择有效的文件夹路径")
return
self.running = True
self.analyze_btn.config(state=tk.DISABLED)
self.stop_btn.config(state=tk.NORMAL)
self.open_btn.config(state=tk.DISABLED)
self.progress_var.set(0)
self.clear_log()
# 在新线程中运行分析
thread = threading.Thread(target=self.analyze_folders, args=(path,))
thread.daemon = True
thread.start()
def stop_analysis(self):
self.running = False
self.log("操作已停止")
self.update_status("操作已停止")
def open_folder(self):
path = self.path_var.get()
if os.path.isdir(path):
try:
# 跨平台打开文件夹
if os.name == 'nt': # Windows
os.startfile(path)
elif os.name == 'posix': # macOS, Linux
subprocess.run(['open', path] if sys.platform == 'darwin' else ['xdg-open', path])
except Exception as e:
messagebox.showerror("错误", f"无法打开文件夹: {str(e)}")
def analyze_folders(self, root_path):
self.log(f"开始分析: {root_path}")
self.update_status("正在扫描文件夹...")
# 获取所有子文件夹
folders = [f for f in os.listdir(root_path) if os.path.isdir(os.path.join(root_path, f))]
total_folders = len(folders)
self.folder_stats = []
if total_folders == 0:
self.log("没有找到子文件夹")
self.update_status("完成 - 没有子文件夹")
self.reset_buttons()
return
# 分析每个文件夹
for i, folder in enumerate(folders):
if not self.running:
break
folder_path = os.path.join(root_path, folder)
self.update_status(f"正在处理: {folder} ({i+1}/{total_folders})")
self.progress_var.set((i / total_folders) * 100)
# 分析文件夹内容
stats = self.analyze_folder(folder_path, folder)
self.folder_stats.append(stats)
# 预览重命名结果
if self.preview_var.get():
self.log(f"文件夹: {folder}")
self.log(f" 视频文件: {stats['video_count']}个, 图片文件: {stats['image_count']}个")
self.log(f" 总大小: {self.format_size(stats['total_size'])}")
if self.rename_var.get() and stats['should_rename']:
self.log(f" 新名称: {stats['new_name']}")
# 实际重命名
if self.rename_var.get() and stats['should_rename']:
try:
new_path = os.path.join(root_path, stats['new_name'])
# 检查新路径是否已存在
if os.path.exists(new_path):
self.log(f"警告: 目标路径已存在, 跳过重命名: {stats['new_name']}")
else:
os.rename(folder_path, new_path)
self.log(f"已重命名: {folder} -> {stats['new_name']}")
except Exception as e:
self.log(f"重命名失败: {str(e)}")
# 完成处理
self.progress_var.set(100)
self.update_status("分析完成")
self.log(f"处理完成: 共处理了 {len(self.folder_stats)} 个文件夹")
self.reset_buttons()
self.open_btn.config(state=tk.NORMAL)
def analyze_folder(self, folder_path, folder_name):
"""分析文件夹内容并返回统计信息"""
video_count = 0
image_count = 0
other_count = 0
total_size = 0
# 遍历文件夹中的所有文件
for root, dirs, files in os.walk(folder_path):
for file in files:
if not self.running:
break
file_path = os.path.join(root, file)
file_ext = os.path.splitext(file)[1].lower()
# 检查文件类型
if file_ext in VIDEO_EXTENSIONS:
video_count += 1
elif file_ext in IMAGE_EXTENSIONS:
image_count += 1
else:
other_count += 1
# 计算文件大小
try:
total_size += os.path.getsize(file_path)
except:
pass
# 确定是否需要重命名(仅包含视频/图片文件)
should_rename = other_count == 0
# 计算文件夹大小(MB或GB)
size_mb = total_size / (1024 ** 2)
size_gb = total_size / (1024 ** 3)
# 生成新名称(根据您的需求改进)
base_name = re.sub(r'\s*\[\d+p\s+\d+v\s+\d+\.\d+G\]$', '', folder_name).strip()
base_name = re.sub(r'\s*\[\d+p\s+\d+\.\d+M\]$', '', base_name).strip()
# 根据内容类型生成不同的后缀
if image_count > 0 and video_count == 0:
# 纯图片文件夹: [图片数量p 大小M]
suffix = f"[{image_count}p {size_mb:.2f}M]"
elif video_count > 0 and image_count == 0:
# 纯视频文件夹: [视频数量v 大小G]
suffix = f"[{video_count}v {size_gb:.2f}G]"
else:
# 混合文件夹: [图片数量p 视频数量v 大小G]
suffix = f"[{image_count}p {video_count}v {size_gb:.2f}G]"
new_name = f"{base_name} {suffix}"
return {
'path': folder_path,
'original_name': folder_name,
'video_count': video_count,
'image_count': image_count,
'other_count': other_count,
'total_size': total_size,
'should_rename': should_rename,
'new_name': new_name
}
def format_size(self, size_bytes):
"""格式化文件大小为易读格式"""
if size_bytes < 1024:
return f"{size_bytes} B"
elif size_bytes < 1024**2:
return f"{size_bytes/1024:.2f} KB"
elif size_bytes < 1024**3:
return f"{size_bytes/(1024**2):.2f} MB"
else:
return f"{size_bytes/(1024**3):.2f} GB"
def log(self, message):
"""向日志区域添加消息"""
self.log_text.config(state=tk.NORMAL)
self.log_text.insert(tk.END, message + "\n")
self.log_text.see(tk.END)
self.log_text.config(state=tk.DISABLED)
def clear_log(self):
"""清空日志"""
self.log_text.config(state=tk.NORMAL)
self.log_text.delete(1.0, tk.END)
self.log_text.config(state=tk.DISABLED)
def update_status(self, message):
"""更新状态栏"""
self.status_var.set(message)
self.root.update()
def reset_buttons(self):
"""重置按钮状态"""
self.analyze_btn.config(state=tk.NORMAL)
self.stop_btn.config(state=tk.DISABLED)
self.running = False
if __name__ == "__main__":
root = tk.Tk()
app = FolderAnalyzerApp(root)
root.mainloop()
```
## 主要改进说明
### 1. 重命名格式优化
在 `analyze_folder` 方法中,我修改了重命名逻辑:
```python
# 根据内容类型生成不同的后缀
if image_count > 0 and video_count == 0:
# 纯图片文件夹: [图片数量p 大小M]
suffix = f"[{image_count}p {size_mb:.2f}M]"
elif video_count > 0 and image_count == 0:
# 纯视频文件夹: [视频数量v 大小G]
suffix = f"[{video_count}v {size_gb:.2f}G]"
else:
# 混合文件夹: [图片数量p 视频数量v 大小G]
suffix = f"[{image_count}p {video_count}v {size_gb:.2f}G]"
```
### 2. 旧标签清理优化
改进了正则表达式,能够同时清理旧格式和新格式的标签:
```python
base_name = re.sub(r'\s*\[\d+p\s+\d+v\s+\d+\.\d+G\]$', '', folder_name).strip()
base_name = re.sub(r'\s*\[\d+p\s+\d+\.\d+M\]$', '', base_name).strip()
```
### 3. 文件大小处理优化
现在根据文件夹内容类型使用不同的单位:
- 纯图片文件夹:使用 MB(兆字节)
- 纯视频文件夹:使用 GB(吉字节)
- 混合文件夹:使用 GB(吉字节)
### 4. 增强错误处理
添加了重命名时的路径存在性检查:
```python
# 检查新路径是否已存在
if os.path.exists(new_path):
self.log(f"警告: 目标路径已存在, 跳过重命名: {stats['new_name']}")
```
## 使用示例
### 输入文件夹结构
```
父文件夹/
├── 旅行照片/ # 包含23张图片,0个视频
├── 家庭视频/ # 包含0张图片,5个视频
├── 婚礼记录/ # 包含15张图片,3个视频
└── 文档备份/ # 包含文档文件(不会被重命名)
```
### 重命名结果
```
父文件夹/
├── 旅行照片 [23p 0.17M] # 纯图片文件夹
├── 家庭视频 [5v 1.25G] # 纯视频文件夹
├── 婚礼记录 [15p 3v 2.85G] # 混合文件夹
└── 文档备份/ # 包含其他文件类型,不被重命名
```
## 功能特点
1. **智能识别**:自动区分纯图片、纯视频和混合文件夹
2. **动态单位**:根据内容类型自动选择大小单位(MB/GB)
3. **安全重命名**:检查目标路径是否存在,避免覆盖
4. **实时预览**:在重命名前预览结果
5. **进度显示**:进度条和状态栏显示当前处理状态
6. **日志记录**:详细记录操作过程和结果