Project Introduction
This is a graphical interface tool developed based on Python to batch rename image files in folders. It can recursively process images in selected folders and all subfolders, and intelligently rename them in the format of "folder name_serial number.extension".
Main functions
- Recursive processing: Automatically scan and process selected folders and all subfolders
- Intelligent renaming: Rename the image to a unified format of "Folder Name_Serial Number.Extension"
- Multilingual support: Provides 7 language interfaces (Chinese, English, Russian, Japanese, German, Portuguese and French)
- Real-time log: Show detailed processing progress and results
- User-friendly: Simple and intuitive graphical interface, simple operation
Supported image formats
- JPG/JPEG
- PNG
- GIF
- BMP
- TIFF
- WEBP
Technology implementation
The project is mainly developed using the Python standard library, and there is no need to install additional third-party libraries. Core functions include:
-
Recursive file processing: use
Traversing the folder structure
- Multilingual support: Store translated text through JSON file, dynamically load
-
Thread processing: use
threading
Module prevents interface from being stuck -
GUI interface: based on
tkinter
Build a user-friendly graphical interface
Complete code
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'} # --- Core renaming logic ---def rename_images_in_folder(folder_path, log_callback): try: folder_name = (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((folder_path)) for filename in items: original_full_path = (folder_path, filename) if (original_full_path): _, ext = (filename) if () in SUPPORTED_EXTENSIONS: new_filename = f"{folder_name}_{count}{ext}" new_full_path = (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 (new_full_path): log_callback(lang_manager.get_text('warning_existing_file').format(filename=filename, new_filename=new_filename)) continue try: (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 (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 (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 part ---class RenamerApp: def __init__(self, master): = master self.lang_manager = LanguageManager() self.update_window_title() self.selected_folder = () self.is_running = False # Create a language selection drop-down box self.create_language_selector() # Folder selection section (master, text=self.lang_manager.get_text('select_folder')).grid(row=1, column=0, padx=5, pady=5) self.folder_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 = (master, text=self.lang_manager.get_text('browse'), command=self.browse_folder) self.browse_button.grid(row=1, column=2, padx=5, pady=5) # Start Button self.rename_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) # Log area (master, text=self.lang_manager.get_text('log')).grid(row=3, column=0, padx=5, pady=5, sticky="w") self.log_area = (master, wrap=, 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') # Layout configuration 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 = () (row=0, column=0, columnspan=3, padx=5, pady=5, sticky="e") # Get the localized name of the current language current_lang_name = languages[current_lang] self.lang_var = (value=current_lang_name) # Create a mapping of language code to localized names self.lang_code_to_name = languages self.lang_name_to_code = {v: k for k, v in ()} self.lang_combobox = (frame, textvariable=self.lang_var, values=list(()), state='readonly', width=10) self.lang_combobox.bind('<<ComboboxSelected>>', self.on_language_change) self.lang_combobox.pack(side=) 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 .grid_slaves(): if isinstance(widget, ): if widget.grid_info()['row'] == 1: # Select folder label (text=self.lang_manager.get_text('select_folder')) elif widget.grid_info()['row'] == 3: # Log label (text=self.lang_manager.get_text('log')) def update_window_title(self): (self.lang_manager.get_text('title')) def log(self, message): def _update_log(): self.log_area.config(state='normal') self.log_area.insert(, message + "\n") self.log_area.see() self.log_area.config(state='disabled') (0, _update_log) def browse_folder(self): if self.is_running: (self.lang_manager.get_text('title'), self.lang_manager.get_text('task_running')) return folder = () if folder: self.selected_folder.set(folder) def start_renaming_thread(self): if self.is_running: (self.lang_manager.get_text('title'), self.lang_manager.get_text('task_running')) return root_dir = self.selected_folder.get() if not root_dir: (self.lang_manager.get_text('title'), self.lang_manager.get_text('select_folder_error')) return if not (root_dir): (self.lang_manager.get_text('title'), self.lang_manager.get_text('invalid_folder_error')) return if not (self.lang_manager.get_text('title'), self.lang_manager.get_text('confirm_operation').format(folder=(root_dir))): return self.log_area.config(state='normal') self.log_area.delete('1.0', ) 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 = (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, ) except Exception as e: (self.lang_manager.get_text('unexpected_error').format(error=str(e))) finally: (0, self.on_rename_complete) def on_rename_complete(self): (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 # --- Main program entry ---if __name__ == "__main__": lang_manager = LanguageManager() root = () app = RenamerApp(root) ()
language_manager.py
import os import json import locale class LanguageManager: def __init__(self): self.current_language = None = {} self.locales_dir = ((__file__), 'locales') self.supported_languages = { 'en': 'English', 'zh': 'Chinese', 'ru': 'Русский', 'ja': 'Japanese', 'de': 'Deutsch', 'pt': 'Português', 'fr': 'Français' } # Automatically detect system language during initialization system_lang = ()[0] self.default_language = 'en' # Use English by default self.load_language(self.default_language) def load_language(self, lang_code): """Load the specified language file""" if lang_code not in self.supported_languages: lang_code = 'en' # Use English by default try: file_path = (self.locales_dir, f'{lang_code}.json') with open(file_path, 'r', encoding='utf-8') as f: = (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): """Get the translated text""" return (key, key) def get_current_language(self): """Get the current language code""" return self.current_language def get_supported_languages(self): """Get a list of supported languages""" return self.supported_languages
How to use
- Clone or download the project code
- Run the program:
python rename_images_gui.py
- Select the root folder to process
- Click the "Start Rename" button
- View processing results in the log area
The above is the detailed content of using Python to implement image batch renaming tool. For more information about Python image renaming, please follow my other related articles!