文件批量重命名工具按规则修改

联启 电脑工具 14

本文目录导读:

文件批量重命名工具按规则修改-第1张图片-电脑手机工具软件下载 - 免费实用工具合集 | 联启科技

  1. 基础版本 - 支持多种命名模式
  2. 图形界面版本 (Tkinter)
  3. 命令行版本
  4. 使用方法
  5. 支持的功能

我来为您提供一个Python文件批量重命名工具,支持多种命名规则:

基础版本 - 支持多种命名模式

import os
import re
from pathlib import Path
class FileRenamer:
    def __init__(self, directory):
        """
        初始化
        :param directory: 目标文件夹路径
        """
        self.directory = Path(directory)
        self.files = []
        self.changes = []
    def scan_files(self, pattern=None, extension=None):
        """
        扫描文件
        :param pattern: 文件名匹配模式(支持通配符)
        :param extension: 文件扩展名过滤
        """
        if extension:
            self.files = list(self.directory.glob(f'*.{extension}'))
        elif pattern:
            self.files = list(self.directory.glob(pattern))
        else:
            self.files = list(self.directory.glob('*'))
        # 只保留文件,不包含目录
        self.files = [f for f in self.files if f.is_file()]
        self.files.sort()
        return self.files
    def preview(self):
        """预览所有更改"""
        print("\n=== 预览修改 ===")
        for old_path, new_path in self.changes:
            print(f"{old_path.name} -> {new_path.name}")
        print(f"总计: {len(self.changes)} 个文件\n")
    def execute(self, confirm=True):
        """
        执行重命名
        :param confirm: 是否确认执行
        """
        if confirm:
            self.preview()
            response = input("确认执行?(y/n): ").lower()
            if response != 'y':
                print("已取消")
                return False
        for old_path, new_path in self.changes:
            try:
                old_path.rename(new_path)
                print(f"✓ {old_path.name} -> {new_path.name}")
            except Exception as e:
                print(f"✗ 重命名 {old_path.name} 失败: {e}")
        print(f"\n完成!重命名了 {len(self.changes)} 个文件")
        return True
    # === 命名规则 ===
    def add_prefix(self, prefix):
        """添加前缀"""
        self.changes = []
        for file in self.files:
            new_name = f"{prefix}{file.name}"
            self.changes.append((file, file.with_name(new_name)))
        return self
    def add_suffix(self, suffix):
        """添加后缀(在扩展名之前)"""
        self.changes = []
        for file in self.files:
            stem = file.stem
            new_name = f"{stem}{suffix}{file.suffix}"
            self.changes.append((file, file.with_name(new_name)))
        return self
    def replace_text(self, old_text, new_text):
        """替换文本"""
        self.changes = []
        for file in self.files:
            new_name = file.name.replace(old_text, new_text)
            self.changes.append((file, file.with_name(new_name)))
        return self
    def remove_text(self, text):
        """删除文本"""
        return self.replace_text(text, "")
    def change_extension(self, new_extension):
        """更改扩展名"""
        if not new_extension.startswith('.'):
            new_extension = f'.{new_extension}'
        self.changes = []
        for file in self.files:
            new_name = f"{file.stem}{new_extension}"
            self.changes.append((file, file.with_name(new_name)))
        return self
    def number_files(self, start=1, padding=2, prefix="", position="prefix"):
        """
        按序号重命名
        :param start: 起始序号
        :param padding: 序号位数(补零)
        :param prefix: 文件名前缀
        :param position: 序号位置(prefix-在文件名前,suffix-在文件名后)
        """
        self.changes = []
        for i, file in enumerate(self.files):
            num = str(start + i).zfill(padding)
            stem = file.stem
            ext = file.suffix
            if position == "prefix":
                new_name = f"{prefix}{num}_{stem}{ext}"
            else:  # suffix
                new_name = f"{stem}_{num}{ext}"
            self.changes.append((file, file.with_name(new_name)))
        return self
    def format_name(self, format_string):
        """
        格式化命名
        支持的占位符:
        {index} - 序号
        {name}  - 原文件名(不含扩展名)
        {ext}   - 扩展名
        {date}  - 当前日期
        {time}  - 当前时间
        """
        from datetime import datetime
        now = datetime.now()
        self.changes = []
        for i, file in enumerate(self.files):
            stem = file.stem
            ext = file.suffix
            new_name = format_string.format(
                index=str(i+1).zfill(3),
                name=stem,
                ext=ext,
                date=now.strftime("%Y%m%d"),
                time=now.strftime("%H%M%S")
            )
            self.changes.append((file, file.with_name(new_name)))
        return self
    def regex_replace(self, pattern, replacement):
        """正则表达式替换"""
        self.changes = []
        for file in self.files:
            new_name = re.sub(pattern, replacement, file.name)
            self.changes.append((file, file.with_name(new_name)))
        return self
    def to_lowercase(self):
        """转为小写"""
        self.changes = []
        for file in self.files:
            new_name = file.name.lower()
            self.changes.append((file, file.with_name(new_name)))
        return self
    def to_uppercase(self):
        """转为大写"""
        self.changes = []
        for file in self.files:
            new_name = file.name.upper()
            self.changes.append((file, file.with_name(new_name)))
        return self
    def remove_spaces(self, replacement="_"):
        """删除空格"""
        return self.replace_text(" ", replacement)
    def undo(self):
        """撤销上次操作"""
        if not self.changes:
            print("没有可撤销的操作")
            return
        changed_files = [(new, old) for old, new in self.changes]
        print("\n=== 撤销修改 ===")
        for old_path, new_path in changed_files:
            try:
                if new_path.exists():  # 只撤销存在的文件
                    new_path.rename(old_path)
                    print(f"✓ {new_path.name} -> {old_path.name}")
            except Exception as e:
                print(f"✗ 撤销 {new_path.name} 失败: {e}")
        self.changes = []
        print("撤销完成")
# === 使用示例 ===
if __name__ == "__main__":
    # 创建重命名器实例
    renamer = FileRenamer("./test_files")  # 替换为你的目标文件夹
    # 扫描所有txt文件
    renamer.scan_files(extension="txt")
    # 应用命名规则(可以链式调用)
    renamer.add_prefix("2024_") \
            .remove_spaces() \
            .to_lowercase()
    # 预览修改
    renamer.preview()
    # 执行重命名
    renamer.execute()

图形界面版本 (Tkinter)

import tkinter as tk
from tkinter import ttk, filedialog, messagebox
import os
from pathlib import Path
class BatchRenamerGUI:
    def __init__(self, root):
        self.root = root
        self.root.title("批量文件重命名工具")
        self.root.geometry("700x500")
        self.directory = ""
        self.files = []
        self.changes = []
        self.setup_ui()
    def setup_ui(self):
        # 主框架
        main_frame = ttk.Frame(self.root, padding="10")
        main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        # 文件夹选择
        ttk.Label(main_frame, text="选择文件夹:").grid(row=0, column=0, sticky=tk.W)
        self.dir_var = tk.StringVar()
        ttk.Entry(main_frame, textvariable=self.dir_var, width=50).grid(row=0, column=1, padx=5)
        ttk.Button(main_frame, text="浏览", command=self.browse_folder).grid(row=0, column=2)
        # 文件过滤
        ttk.Label(main_frame, text="文件类型:").grid(row=1, column=0, sticky=tk.W, pady=5)
        self.ext_var = tk.StringVar(value="所有文件")
        ext_combo = ttk.Combobox(main_frame, textvariable=self.ext_var, width=20)
        ext_combo['values'] = ('所有文件', '.txt', '.jpg', '.png', '.pdf', '.docx', '.xlsx', '.csv')
        ext_combo.grid(row=1, column=1, sticky=tk.W, pady=5)
        ttk.Button(main_frame, text="扫描文件", command=self.scan_files).grid(row=1, column=2, pady=5)
        # 文件列表
        ttk.Label(main_frame, text="文件列表:").grid(row=2, column=0, sticky=tk.W, pady=5)
        self.file_listbox = tk.Listbox(main_frame, height=10, width=80)
        self.file_listbox.grid(row=3, column=0, columnspan=3, pady=5)
        # 滚动条
        scrollbar = ttk.Scrollbar(main_frame, orient=tk.VERTICAL, command=self.file_listbox.yview)
        scrollbar.grid(row=3, column=3, sticky=(tk.N, tk.S))
        self.file_listbox.configure(yscrollcommand=scrollbar.set)
        # 命名规则框架
        rules_frame = ttk.LabelFrame(main_frame, text="命名规则", padding="5")
        rules_frame.grid(row=4, column=0, columnspan=3, pady=10, sticky=(tk.W, tk.E))
        # 添加前缀
        ttk.Label(rules_frame, text="添加前缀:").grid(row=0, column=0, padx=5)
        self.prefix_var = tk.StringVar()
        ttk.Entry(rules_frame, textvariable=self.prefix_var, width=15).grid(row=0, column=1)
        ttk.Button(rules_frame, text="应用", command=lambda: self.apply_rule("prefix")).grid(row=0, column=2, padx=5)
        # 添加后缀
        ttk.Label(rules_frame, text="添加后缀:").grid(row=0, column=3, padx=5)
        self.suffix_var = tk.StringVar()
        ttk.Entry(rules_frame, textvariable=self.suffix_var, width=15).grid(row=0, column=4)
        ttk.Button(rules_frame, text="应用", command=lambda: self.apply_rule("suffix")).grid(row=0, column=5, padx=5)
        # 替换文本
        ttk.Label(rules_frame, text="替换:").grid(row=1, column=0, padx=5, pady=5)
        self.replace_old_var = tk.StringVar()
        ttk.Entry(rules_frame, textvariable=self.replace_old_var, width=10).grid(row=1, column=1, pady=5)
        ttk.Label(rules_frame, text="→").grid(row=1, column=2)
        self.replace_new_var = tk.StringVar()
        ttk.Entry(rules_frame, textvariable=self.replace_new_var, width=10).grid(row=1, column=3, pady=5)
        ttk.Button(rules_frame, text="替换", command=lambda: self.apply_rule("replace")).grid(row=1, column=4, pady=5)
        # 序号重命名
        ttk.Label(rules_frame, text="序号:").grid(row=2, column=0, padx=5)
        self.num_start_var = tk.StringVar(value="1")
        ttk.Spinbox(rules_frame, from_=0, to=999, textvariable=self.num_start_var, width=5).grid(row=2, column=1)
        ttk.Label(rules_frame, text="位数:").grid(row=2, column=2)
        self.num_padding_var = tk.StringVar(value="2")
        ttk.Spinbox(rules_frame, from_=1, to=5, textvariable=self.num_padding_var, width=5).grid(row=2, column=3)
        ttk.Button(rules_frame, text="编号", command=lambda: self.apply_rule("number")).grid(row=2, column=4)
        # 操作按钮
        button_frame = ttk.Frame(main_frame)
        button_frame.grid(row=5, column=0, columnspan=3, pady=10)
        ttk.Button(button_frame, text="预览修改", command=self.preview_changes).pack(side=tk.LEFT, padx=5)
        ttk.Button(button_frame, text="执行重命名", command=self.execute_rename).pack(side=tk.LEFT, padx=5)
        ttk.Button(button_frame, text="重置", command=self.reset).pack(side=tk.LEFT, padx=5)
        # 状态栏
        self.status_var = tk.StringVar(value="就绪")
        status_bar = ttk.Label(main_frame, textvariable=self.status_var, relief=tk.SUNKEN, anchor=tk.W)
        status_bar.grid(row=6, column=0, columnspan=3, sticky=(tk.W, tk.E), pady=5)
    def browse_folder(self):
        directory = filedialog.askdirectory()
        if directory:
            self.dir_var.set(directory)
            self.scan_files()
    def scan_files(self):
        directory = self.dir_var.get()
        if not directory:
            messagebox.showerror("错误", "请选择文件夹")
            return
        self.files = []
        self.file_listbox.delete(0, tk.END)
        ext = self.ext_var.get()
        if ext == "所有文件":
            pattern = "*"
        else:
            pattern = f"*{ext}"
        for file in Path(directory).glob(pattern):
            if file.is_file():
                self.files.append(file)
                self.file_listbox.insert(tk.END, file.name)
        self.status_var.set(f"找到 {len(self.files)} 个文件")
    def apply_rule(self, rule_type):
        if not self.files:
            messagebox.showerror("错误", "请先扫描文件")
            return
        from datetime import datetime
        self.changes = []
        for i, file in enumerate(self.files):
            stem = file.stem
            ext = file.suffix
            if rule_type == "prefix":
                new_name = f"{self.prefix_var.get()}{file.name}"
            elif rule_type == "suffix":
                new_name = f"{stem}{self.suffix_var.get()}{ext}"
            elif rule_type == "replace":
                new_name = file.name.replace(self.replace_old_var.get(), self.replace_new_var.get())
            elif rule_type == "number":
                start = int(self.num_start_var.get())
                padding = int(self.num_padding_var.get())
                num = str(start + i).zfill(padding)
                new_name = f"{num}_{file.name}"
            else:
                continue
            self.changes.append((file, file.with_name(new_name)))
        self.status_var.set(f"已应用规则,待处理 {len(self.changes)} 个文件")
        self.preview_changes()
    def preview_changes(self):
        if not self.changes:
            messagebox.showinfo("提示", "没有待处理的更改")
            return
        preview_text = "=== 预览修改 ===\n\n"
        for old, new in self.changes:
            preview_text += f"  {old.name}\n  → {new.name}\n\n"
        preview_text += f"\n总计: {len(self.changes)} 个文件"
        messagebox.showinfo("预览修改", preview_text)
    def execute_rename(self):
        if not self.changes:
            messagebox.showerror("错误", "没有待执行的更改")
            return
        if not messagebox.askyesno("确认", f"确定要重命名 {len(self.changes)} 个文件吗?"):
            return
        success = 0
        failed = 0
        for old, new in self.changes:
            try:
                if not new.exists():  # 避免覆盖已有文件
                    old.rename(new)
                    success += 1
                else:
                    failed += 1
                    messagebox.showwarning("警告", f"目标文件已存在: {new.name}")
            except Exception as e:
                failed += 1
                print(f"重命名失败: {e}")
        self.status_var.set(f"完成!成功: {success}, 失败: {failed}")
        self.scan_files()  # 刷新文件列表
        self.changes = []
    def reset(self):
        self.changes = []
        self.status_var.set("已重置")
if __name__ == "__main__":
    root = tk.Tk()
    app = BatchRenamerGUI(root)
    root.mainloop()

命令行版本

#!/bin/bash
# file_renamer.sh - 命令行批量重命名工具
# 使用方法
usage() {
    echo "批量文件重命名工具"
    echo "用法: $0 [选项]"
    echo ""
    echo "选项:"
    echo "  -d DIR     目标文件夹 (默认: 当前目录)"
    echo "  -e EXT     文件扩展名过滤"
    echo "  -p PREFIX  添加前缀"
    echo "  -s SUFFIX  添加后缀"
    echo "  -r OLD NEW 替换文本"
    echo "  -n         序号重命名"
    echo "  -l         转为小写"
    echo "  -u         转为大写"
    echo "  --dry-run  预览模式"
    echo ""
    echo "示例:"
    echo "  $0 -d ./images -e jpg -p photo_"
    echo "  $0 -e txt -r 'old' 'new'"
    echo "  $0 -e pdf -n --dry-run"
}
# 解析参数
DIR="."
EXT=""
PREFIX=""
SUFFIX=""
REPLACE_OLD=""
REPLACE_NEW=""
NUMBER=false
LOWERCASE=false
UPPERCASE=false
DRY_RUN=false
while [[ $# -gt 0 ]]; do
    case $1 in
        -d) DIR="$2"; shift 2 ;;
        -e) EXT="$2"; shift 2 ;;
        -p) PREFIX="$2"; shift 2 ;;
        -s) SUFFIX="$2"; shift 2 ;;
        -r) REPLACE_OLD="$2"; REPLACE_NEW="$3"; shift 3 ;;
        -n) NUMBER=true; shift ;;
        -l) LOWERCASE=true; shift ;;
        -u) UPPERCASE=true; shift ;;
        --dry-run) DRY_RUN=true; shift ;;
        -h|--help) usage; exit 0 ;;
        *) echo "未知选项: $1"; usage; exit 1 ;;
    esac
done
# 扫描文件
if [[ -n "$EXT" ]]; then
    files=("$DIR"/*."$EXT")
else
    files=("$DIR"/*)
fi
count=0
for file in "${files[@]}"; do
    if [[ -f "$file" ]]; then
        dir=$(dirname "$file")
        basename=$(basename "$file")
        filename="${basename%.*}"
        extension="${basename##*.}"
        newname="$basename"
        # 应用规则
        [[ -n "$PREFIX" ]] && newname="$PREFIX$newname"
        [[ -n "$SUFFIX" ]] && newname="${filename}${SUFFIX}.${extension}"
        [[ -n "$REPLACE_OLD" ]] && newname="${newname//$REPLACE_OLD/$REPLACE_NEW}"
        if [[ "$LOWERCASE" == true ]]; then
            newname=$(echo "$newname" | tr '[:upper:]' '[:lower:]')
        fi
        if [[ "$UPPERCASE" == true ]]; then
            newname=$(echo "$newname" | tr '[:lower:]' '[:upper:]')
        fi
        if [[ "$NUMBER" == true ]]; then
            count=$((count + 1))
            num=$(printf "%02d" $count)
            newname="${num}_${filename}.${extension}"
        fi
        # 预览或执行
        if [[ "$DRY_RUN" == true ]]; then
            echo "[预览] $basename -> $newname"
        else
            if [[ "$basename" != "$newname" ]]; then
                mv "$file" "$dir/$newname"
                echo "[执行] $basename -> $newname"
            fi
        fi
    fi
done
echo "处理完成!"

使用方法

Python版本:

  1. 创建Python文件并运行
  2. 修改 directory 为你的目标文件夹
  3. 调用不同的重命名方法

图形界面版本:

  1. 运行程序
  2. 选择文件夹
  3. 选择文件类型
  4. 应用不同的命名规则
  5. 预览并执行

命令行版本:

# 示例
./file_renamer.sh -d ./photos -e jpg -p "vacation_"
./file_renamer.sh -e txt -r "old" "new"
./file_renamer.sh -e pdf -n --dry-run

支持的功能

  • ✅ 添加前缀/后缀
  • ✅ 替换/删除文本
  • ✅ 序号重命名
  • ✅ 大小写转换
  • ✅ 正则表达式替换
  • ✅ 撤销操作
  • ✅ 预览修改
  • ✅ 文件类型过滤
  • ✅ 图形界面(可选)

需要更多定制功能或改进,请告诉我!

标签: 文件批量重命名工具

抱歉,评论功能暂时关闭!