AI生成应用:图片批量重命名工具 - 自动化整理您的图片库
图片批量重命名工具 - 自动化整理您的图片库
GitHub项目地址: https://github.com/dependon/renameImage
项目介绍
这是一个基于Python开发的图形界面工具,用于批量重命名文件夹中的图片文件。它能够递归处理选定文件夹及其所有子文件夹中的图片,按照"文件夹名_序号.扩展名"的格式进行智能重命名。
主要功能
- 递归处理: 自动扫描并处理选定文件夹及其所有子文件夹
- 智能重命名: 将图片重命名为"文件夹名_序号.扩展名"的统一格式
- 多语言支持: 提供7种语言界面(中文、英文、俄语、日语、德语、葡萄牙语和法语)
- 实时日志: 显示详细的处理进度和结果
- 用户友好: 简洁直观的图形界面,操作简单
支持的图片格式
- JPG/JPEG
- PNG
- GIF
- BMP
- TIFF
- WEBP
技术实现
项目主要使用Python标准库开发,无需额外安装第三方库。核心功能包括:
- 递归文件处理: 使用
os.walk
遍历文件夹结构 - 多语言支持: 通过JSON文件存储翻译文本,动态加载
- 线程处理: 使用
threading
模块防止界面卡顿 - GUI界面: 基于
tkinter
构建用户友好的图形界面
完整代码
# rename_images_gui.py
import os
import tkinter as tk
from tkinter import filedialog, messagebox, scrolledtext, ttk
import threading
from language_manager import LanguageManager
SUPPORTED_EXTENSIONS = {'.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff', '.webp'}
# --- 核心重命名逻辑 ---
def rename_images_in_folder(folder_path, log_callback):
try:
folder_name = os.path.basename(folder_path)
if not folder_name:
log_callback(lang_manager.get_text('skip_root').format(folder_path=folder_path))
return 0
count = 1
renamed_count = 0
log_callback(lang_manager.get_text('start_processing').format(folder_path=folder_path))
items = sorted(os.listdir(folder_path))
for filename in items:
original_full_path = os.path.join(folder_path, filename)
if os.path.isfile(original_full_path):
_, ext = os.path.splitext(filename)
if ext.lower() in SUPPORTED_EXTENSIONS:
new_filename = f"{folder_name}_{count}{ext}"
new_full_path = os.path.join(folder_path, new_filename)
if original_full_path == new_full_path:
log_callback(lang_manager.get_text('skip_same_name').format(filename=filename))
count += 1
continue
elif os.path.exists(new_full_path):
log_callback(lang_manager.get_text('warning_existing_file').format(filename=filename, new_filename=new_filename))
continue
try:
os.rename(original_full_path, new_full_path)
log_callback(lang_manager.get_text('success').format(filename=filename, new_filename=new_filename))
renamed_count += 1
count += 1
except OSError as e:
log_callback(lang_manager.get_text('error_rename').format(filename=filename, error=str(e)))
log_callback(lang_manager.get_text('folder_processed').format(folder_path=folder_path, renamed_count=renamed_count))
return renamed_count
except Exception as e:
log_callback(lang_manager.get_text('unexpected_error').format(error=str(e)))
return 0
def rename_images_recursively(root_dir, log_callback):
total_renamed = 0
if not os.path.isdir(root_dir):
log_callback(lang_manager.get_text('invalid_folder_error'))
return 0
log_callback(lang_manager.get_text('recursive_start').format(root_dir=root_dir))
for dirpath, dirnames, filenames in os.walk(root_dir, topdown=True):
renamed_in_folder = rename_images_in_folder(dirpath, log_callback)
total_renamed += renamed_in_folder
log_callback(lang_manager.get_text('recursive_complete').format(total_renamed=total_renamed))
return total_renamed
# --- GUI 部分 ---
class RenamerApp:
def __init__(self, master):
self.master = master
self.lang_manager = LanguageManager()
self.update_window_title()
self.selected_folder = tk.StringVar()
self.is_running = False
# 创建语言选择下拉框
self.create_language_selector()
# 文件夹选择部分
tk.Label(master, text=self.lang_manager.get_text('select_folder')).grid(row=1, column=0, padx=5, pady=5)
self.folder_entry = tk.Entry(master, textvariable=self.selected_folder, width=50, state='readonly')
self.folder_entry.grid(row=1, column=1, padx=5, pady=5, sticky="ew")
self.browse_button = tk.Button(master, text=self.lang_manager.get_text('browse'), command=self.browse_folder)
self.browse_button.grid(row=1, column=2, padx=5, pady=5)
# 开始按钮
self.rename_button = tk.Button(master, text=self.lang_manager.get_text('start_rename'), command=self.start_renaming_thread)
self.rename_button.grid(row=2, column=0, columnspan=3, padx=5, pady=10)
# 日志区域
tk.Label(master, text=self.lang_manager.get_text('log')).grid(row=3, column=0, padx=5, pady=5, sticky="w")
self.log_area = scrolledtext.ScrolledText(master, wrap=tk.WORD, height=15, width=70)
self.log_area.grid(row=4, column=0, columnspan=3, padx=5, pady=5, sticky="nsew")
self.log_area.config(state='disabled')
# 布局配置
master.grid_columnconfigure(1, weight=1)
master.grid_rowconfigure(4, weight=1)
def create_language_selector(self):
languages = self.lang_manager.get_supported_languages()
current_lang = self.lang_manager.get_current_language()
frame = tk.Frame(self.master)
frame.grid(row=0, column=0, columnspan=3, padx=5, pady=5, sticky="e")
# 获取当前语言的本地化名称
current_lang_name = languages[current_lang]
self.lang_var = tk.StringVar(value=current_lang_name)
# 创建语言代码到本地化名称的映射
self.lang_code_to_name = languages
self.lang_name_to_code = {v: k for k, v in languages.items()}
self.lang_combobox = ttk.Combobox(frame, textvariable=self.lang_var, values=list(languages.values()), state='readonly', width=10)
self.lang_combobox.bind('<<ComboboxSelected>>', self.on_language_change)
self.lang_combobox.pack(side=tk.RIGHT)
def on_language_change(self, event=None):
selected_lang_name = self.lang_var.get()
selected_lang_code = self.lang_name_to_code[selected_lang_name]
if self.lang_manager.load_language(selected_lang_code):
self.update_ui_texts()
def update_ui_texts(self):
self.update_window_title()
self.browse_button.config(text=self.lang_manager.get_text('browse'))
self.rename_button.config(text=self.lang_manager.get_text('start_rename') if not self.is_running else self.lang_manager.get_text('processing'))
# Update label texts
for widget in self.master.grid_slaves():
if isinstance(widget, tk.Label):
if widget.grid_info()['row'] == 1: # Select folder label
widget.config(text=self.lang_manager.get_text('select_folder'))
elif widget.grid_info()['row'] == 3: # Log label
widget.config(text=self.lang_manager.get_text('log'))
def update_window_title(self):
self.master.title(self.lang_manager.get_text('title'))
def log(self, message):
def _update_log():
self.log_area.config(state='normal')
self.log_area.insert(tk.END, message + "\n")
self.log_area.see(tk.END)
self.log_area.config(state='disabled')
self.master.after(0, _update_log)
def browse_folder(self):
if self.is_running:
messagebox.showwarning(self.lang_manager.get_text('title'), self.lang_manager.get_text('task_running'))
return
folder = filedialog.askdirectory()
if folder:
self.selected_folder.set(folder)
def start_renaming_thread(self):
if self.is_running:
messagebox.showwarning(self.lang_manager.get_text('title'), self.lang_manager.get_text('task_running'))
return
root_dir = self.selected_folder.get()
if not root_dir:
messagebox.showerror(self.lang_manager.get_text('title'), self.lang_manager.get_text('select_folder_error'))
return
if not os.path.isdir(root_dir):
messagebox.showerror(self.lang_manager.get_text('title'), self.lang_manager.get_text('invalid_folder_error'))
return
if not messagebox.askyesno(self.lang_manager.get_text('title'),
self.lang_manager.get_text('confirm_operation').format(folder=os.path.basename(root_dir))):
return
self.log_area.config(state='normal')
self.log_area.delete('1.0', tk.END)
self.log_area.config(state='disabled')
self.rename_button.config(state='disabled', text=self.lang_manager.get_text('processing'))
self.browse_button.config(state='disabled')
self.is_running = True
self.rename_thread = threading.Thread(target=self.run_rename_task, args=(root_dir,))
self.rename_thread.daemon = True
self.rename_thread.start()
def run_rename_task(self, root_dir):
try:
rename_images_recursively(root_dir, self.log)
except Exception as e:
self.log(self.lang_manager.get_text('unexpected_error').format(error=str(e)))
finally:
self.master.after(0, self.on_rename_complete)
def on_rename_complete(self):
messagebox.showinfo(self.lang_manager.get_text('title'), self.lang_manager.get_text('completed'))
self.rename_button.config(state='normal', text=self.lang_manager.get_text('start_rename'))
self.browse_button.config(state='normal')
self.is_running = False
# --- 主程序入口 ---
if __name__ == "__main__":
lang_manager = LanguageManager()
root = tk.Tk()
app = RenamerApp(root)
root.mainloop()
# language_manager.py
import os
import json
import locale
class LanguageManager:
def __init__(self):
self.current_language = None
self.translations = {}
self.locales_dir = os.path.join(os.path.dirname(__file__), 'locales')
self.supported_languages = {
'en': 'English',
'zh': '中文',
'ru': 'Русский',
'ja': '日本語',
'de': 'Deutsch',
'pt': 'Português',
'fr': 'Français'
}
# 初始化时自动检测系统语言
system_lang = locale.getdefaultlocale()[0]
self.default_language = 'en' # 默认使用英语
self.load_language(self.default_language)
def load_language(self, lang_code):
"""加载指定的语言文件"""
if lang_code not in self.supported_languages:
lang_code = 'en' # 默认使用英语
try:
file_path = os.path.join(self.locales_dir, f'{lang_code}.json')
with open(file_path, 'r', encoding='utf-8') as f:
self.translations = json.load(f)
self.current_language = lang_code
return True
except Exception as e:
print(f'Error loading language file: {e}')
return False
def get_text(self, key):
"""获取翻译文本"""
return self.translations.get(key, key)
def get_current_language(self):
"""获取当前语言代码"""
return self.current_language
def get_supported_languages(self):
"""获取支持的语言列表"""
return self.supported_languages
使用方法
- 克隆或下载项目代码
- 运行程序:
python rename_images_gui.py
- 选择要处理的根文件夹
- 点击"开始重命名"按钮
- 在日志区域查看处理结果
声明
本项目介绍、博客文章和所有相关内容均由AI生成。
这个工具非常适合摄影师、设计师或需要整理大量图片的用户。它的递归处理和多语言支持使其成为一个非常实用的工具。
本文由博客一文多发平台 OpenWrite 发布!
AI生成应用:图片批量重命名工具 - 自动化整理您的图片库的更多相关文章
- TotalCommander使用方法,如何对图片批量重命名
1 文件或文件夹重命名 F2 2 计算所有文件夹的大小 A/t+Shift+Enter.(这样对于文件的更新操作就更加快捷有效了,比如我的文档里面只有若干个子文件夹有更新,则别的都不用动,只要修改那些 ...
- Python批量重命名 工具贴(一)
说明 由于在处理图片数据和其他数据时,经常需要对数据进行批量重命名操作,每次使用时都需要重写,非常不便,因此记录下重命名代码方便后续使用. 文件结构说明 参数说明: path为输入路径 image_t ...
- Python 入门学习(贰)文件/文件夹正则表达式批量重命名工具
基于 Udacity 的 Python 入门课程 Programming Foundations with Python 基于 Python 2.7 思路 Project 2 是一个去除文件名中所有数 ...
- Python 写了一个批量生成文件夹和批量重命名的工具
Python 写了一个批量生成文件夹和批量重命名的工具 目录 Python 写了一个批量生成文件夹和批量重命名的工具 演示 功能 1. 可以读取excel内容,使用excel单元格内容进行新建文件夹, ...
- linux下rename用法--批量重命名
Linux的rename 命令有两个版本,一个是C语言版本的,一个是Perl语言版本的,早期的Linux发行版基本上使用的是C语言版本的,现在已经很难见到C语言版本的了, 由于历史原因,在Perl语言 ...
- linux下rename用法--批量重命名 转
原文地址:https://www.cnblogs.com/hester/p/5615871.html Linux的rename 命令有两个版本,一个是C语言版本的,一个是Perl语言版本的,早期的Li ...
- Excel 批量重命名照片
理历史照片的时候发现,用文件夹进行分类之后,还有很多照片,如果继续分类,就会导致每个文件夹照片过少,查看不便,但是如果不分类,手机原始的命名方式没有办法满足查看需求,故而,产生了对照片进行批量重命名的 ...
- rename命令和批量重命名
本文为转载文章,转发自 https://blog.csdn.net/GGxiaobai/article/details/53507454 早期版本的rename是C语言版本,如今新的Ubuntu中采用 ...
- 大学MOOC课程视频下载、流文件合并、批量重命名、b站视频下载及学习课程视频推荐
计算机行业技术更新快,编程语言种类多,在当今大数据和人工智能的时代,为了能在相关领域有所成就,就必须掌握好python.R等语言,较好的数学基础和深入的行业背景知识.计算机从业人员务必践行" ...
- 使用java对文件批量重命名
有时候从网络上下载的电视剧或者动漫,名字上都会被该网站加上前缀或者后缀,如图: 那么处女座的同学就不同意了,不行,我就是想让它按照我的习惯方式命名!但是呢,一个个修改是不是特别麻烦,如果是上百个呢?如 ...
随机推荐
- 『Python底层原理』--异步机制(async/await)
在现代编程中,并发是提高程序效率的关键技术之一,它允许程序同时执行多个任务,充分利用系统资源. 本文将深入探讨 Python 中的async/await机制,从并发编程基础讲起,逐步剖析其工作原理和实 ...
- Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
引言:AI技术新纪元的破局者 2025年3月6日凌晨,武汉Monica团队正式发布全球首款通用AI代理系统Manus,该工具在GitHub开源社区引发热议,单日Star数突破5万.与传统对话式AI不同 ...
- Vite项目入口文件
官方文档:https://cn.vitejs.dev/guide/#index-html-and-project-root
- grpc unable to determine Go import path for
前言 在 proto 文件夹下执行如下命令: $ protoc --go_out=plugins=grpc:. *.proto 报错:无法确定Go导入路径 protoc-gen-go: unable ...
- 运维 —— IMP-00030: failed to create file import_sys for write
IMP-00030: failed to create file import_sys for writeIMP-00000: Import terminated unsuccessfully原因:操 ...
- Object类--toString方法--java进阶day05
1.Object类.以及通用的类 2.toString方法 默认的toString方法,返回的是地址值(全类名再加上通过地址值算出来的十六进制哈希值) . 为什么打印语句会自动调用toString方法 ...
- AI 应用思考
之前看到过一个理论,创新技术的三个阶段:新技术创造-精英服务-平民化 技术扩散的三阶段理论模型 1. 创新垄断期(精英创造阶段)技术革命初期,创新活动高度依赖知识密集型投入.AI发展呈现"分 ...
- 【软件】DVDStyler报错找不到VOB文件
DVDStyler失败报错找不到VOB文件 零.错误如下 ERR: 2 opening input video file "D:\Minuhy\Desktop\dvd\t\dvd-cache ...
- Visual Studio 外部工具中添加 git-bash
引言 旧版的 Visual Studio 没有集成 git 工具,并且自己也习惯用 git-bash 命令行来操作, 那么如何在旧版的 Visual Studio 快速打开 git-bash 终端呢? ...
- Nginx 301永久性转移
我有个域名www.taadis.com, 想永久性转移到taadis.com. 前言 看到很多网友的做法是把taadis.com & www.taadis.com等多个域名放到一个server ...