使用Python實(shí)現(xiàn)圖片批量重命名工具
項(xiàng)目介紹
這是一個(gè)基于Python開發(fā)的圖形界面工具,用于批量重命名文件夾中的圖片文件。它能夠遞歸處理選定文件夾及其所有子文件夾中的圖片,按照"文件夾名_序號(hào).擴(kuò)展名"的格式進(jìn)行智能重命名。
主要功能
- 遞歸處理: 自動(dòng)掃描并處理選定文件夾及其所有子文件夾
- 智能重命名: 將圖片重命名為"文件夾名_序號(hào).擴(kuò)展名"的統(tǒng)一格式
- 多語言支持: 提供7種語言界面(中文、英文、俄語、日語、德語、葡萄牙語和法語)
- 實(shí)時(shí)日志: 顯示詳細(xì)的處理進(jìn)度和結(jié)果
- 用戶友好: 簡(jiǎn)潔直觀的圖形界面,操作簡(jiǎn)單
支持的圖片格式
- JPG/JPEG
- PNG
- GIF
- BMP
- TIFF
- WEBP
技術(shù)實(shí)現(xiàn)
項(xiàng)目主要使用Python標(biāo)準(zhǔn)庫開發(fā),無需額外安裝第三方庫。核心功能包括:
- 遞歸文件處理: 使用
os.walk遍歷文件夾結(jié)構(gòu) - 多語言支持: 通過JSON文件存儲(chǔ)翻譯文本,動(dòng)態(tài)加載
- 線程處理: 使用
threading模塊防止界面卡頓 - GUI界面: 基于
tkinter構(gòu)建用戶友好的圖形界面
完整代碼
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
# 創(chuàng)建語言選擇下拉框
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)
# 日志區(qū)域
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")
# 獲取當(dāng)前語言的本地化名稱
current_lang_name = languages[current_lang]
self.lang_var = tk.StringVar(value=current_lang_name)
# 創(chuàng)建語言代碼到本地化名稱的映射
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'
}
# 初始化時(shí)自動(dòng)檢測(cè)系統(tǒng)語言
system_lang = locale.getdefaultlocale()[0]
self.default_language = 'en' # 默認(rèn)使用英語
self.load_language(self.default_language)
def load_language(self, lang_code):
"""加載指定的語言文件"""
if lang_code not in self.supported_languages:
lang_code = 'en' # 默認(rèn)使用英語
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):
"""獲取當(dāng)前語言代碼"""
return self.current_language
def get_supported_languages(self):
"""獲取支持的語言列表"""
return self.supported_languages
使用方法
- 克隆或下載項(xiàng)目代碼
- 運(yùn)行程序:
python rename_images_gui.py - 選擇要處理的根文件夾
- 點(diǎn)擊"開始重命名"按鈕
- 在日志區(qū)域查看處理結(jié)果
以上就是使用Python實(shí)現(xiàn)圖片批量重命名工具的詳細(xì)內(nèi)容,更多關(guān)于Python圖片重命名的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用Python爬蟲框架獲取HTML網(wǎng)頁中指定區(qū)域的數(shù)據(jù)
在當(dāng)今互聯(lián)網(wǎng)時(shí)代,數(shù)據(jù)已經(jīng)成為了一種寶貴的資源,無論是進(jìn)行市場(chǎng)分析、輿情監(jiān)控,還是進(jìn)行學(xué)術(shù)研究,獲取網(wǎng)頁中的數(shù)據(jù)都是一個(gè)非常重要的步驟,Python提供了多種爬蟲框架來幫助我們高效地獲取網(wǎng)頁數(shù)據(jù),本文將詳細(xì)介紹如何使用Python爬蟲框架來獲取HTML網(wǎng)頁中指定區(qū)域的數(shù)據(jù)2025-03-03
python字典各式各樣操作從基礎(chǔ)到高級(jí)全面示例詳解
在Python中,字典(Dictionary)是一種強(qiáng)大而靈活的數(shù)據(jù)結(jié)構(gòu),它允許你存儲(chǔ)和檢索鍵值對(duì),本文將深入探討Python中各式各樣的字典操作,包括基本操作、高級(jí)操作以及一些實(shí)用的技巧,通過全面的示例代碼,將展示如何充分發(fā)揮字典在Python編程中的優(yōu)勢(shì)2023-12-12
python?dataframe獲得指定行列實(shí)戰(zhàn)代碼
對(duì)于一個(gè)DataFrame,常常需要篩選出某列為指定值的行,下面這篇文章主要給大家介紹了關(guān)于python?dataframe獲得指定行列的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-12-12
python使用hdfs3模塊對(duì)hdfs進(jìn)行操作詳解
這篇文章主要介紹了python使用hdfs3模塊對(duì)hdfs進(jìn)行操作詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-06-06
Python網(wǎng)絡(luò)請(qǐng)求模塊urllib與requests使用介紹
網(wǎng)絡(luò)爬蟲的第一步就是根據(jù)URL,獲取網(wǎng)頁的HTML信息。在Python3中,可以使用urllib和requests進(jìn)行網(wǎng)頁數(shù)據(jù)獲取,這篇文章主要介紹了Python網(wǎng)絡(luò)請(qǐng)求模塊urllib與requests使用2022-10-10

