乐于分享
好东西不私藏

(免安装软件分享)文件重命名批量处理

(免安装软件分享)文件重命名批量处理
 文件重命名,最近做文件归档,扫描成的PDF文件经常修改,如果用excel vba 也可以实现,只不过每次都需要提取文件,没有用python编写的这么直观,打包后更容易操作;
打包程序自测可用(WIM11系统测试),没问题,链接放到下方,自取,有时间限制哦

链接:https://pan.baidu.com/s/11FP1Q4HEmk3XU78nGIRs2Q?pwd=8j87 

完整代码放到文章末尾,
已关注
关注
重播 分享

import os

import tkinter as tk

from tkinter import filedialog, messagebox

classBatchRenameApp:

def__init__(selfroot):

self.root = root

self.root.geometry("850x550")

self.current_dir =""

self.old_filenames = []      # 原始文件名列表

self.entry_widgets = []      # 新文件名输入框列表

self.create_widgets()

defcreate_widgets(self):

# 顶部:选择文件夹

        top_frame = tk.Frame(self.root)

        top_frame.pack(pady=10fill=tk.X, padx=10)

        tk.Button(top_frame, text="选择文件夹"command=self.select_folder).pack(side=tk.LEFTpadx=5)

self.path_label = tk.Label(top_frame, text="未选择文件夹"anchor="w"relief=tk.SUNKEN)

self.path_label.pack(side=tk.LEFTfill=tk.X, expand=Truepadx=5)

# 提示标签

        info_label = tk.Label(self.root, text="💡 提示:在右侧任意输入框中按 Ctrl+V 可批量粘贴多行新文件名;点击下方按钮可复制所有新文件名",

fg="blue"anchor="w")

        info_label.pack(pady=(0,5), padx=10fill=tk.X)

# 标题行

        title_frame = tk.Frame(self.root)

        title_frame.pack(pady=5fill=tk.X, padx=10)

        tk.Label(title_frame, text="原文件名"width=35anchor="center"font=("Arial"10"bold")).pack(side=tk.LEFTpadx=5)

        tk.Label(title_frame, text="新文件名(需包含后缀)"width=45anchor="center"font=("Arial"10"bold")).pack(side=tk.LEFTpadx=5)

# 滚动区域(Canvas + Scrollbar)

        canvas = tk.Canvas(self.root)

        scrollbar = tk.Scrollbar(self.root, orient="vertical"command=canvas.yview)

self.scrollable_frame = tk.Frame(canvas)

self.scrollable_frame.bind("<Configure>"lambdae: canvas.configure(scrollregion=canvas.bbox("all")))

        canvas.create_window((00), window=self.scrollable_frame, anchor="nw")

        canvas.configure(yscrollcommand=scrollbar.set)

        canvas.pack(side=tk.LEFTfill=tk.BOTHexpand=Truepadx=(10,0), pady=10)

        scrollbar.pack(side=tk.RIGHTfill=tk.Y, pady=10)

# 底部按钮区域:垂直排列

        bottom_frame = tk.Frame(self.root)

        bottom_frame.pack(pady=10fill=tk.X)

self.rename_btn = tk.Button(bottom_frame, text="开始重命名"command=self.rename_files, state=tk.DISABLED)

self.rename_btn.pack(side=tk.TOPpady=2)

self.copy_btn = tk.Button(bottom_frame, text="复制所有新文件名"command=self.copy_all_new_names, state=tk.DISABLED)

self.copy_btn.pack(side=tk.TOPpady=2)

self.status_label = tk.Label(bottom_frame, text="就绪"fg="blue")

self.status_label.pack(side=tk.TOPpady=2)

defselect_folder(self):

        folder = filedialog.askdirectory()

if folder:

self.current_dir = folder

self.path_label.config(text=self.current_dir)

self.load_files()

defload_files(self):

# 清空旧数据

for widget inself.scrollable_frame.winfo_children():

            widget.destroy()

self.old_filenames.clear()

self.entry_widgets.clear()

ifnot os.path.isdir(self.current_dir):

self.copy_btn.config(state=tk.DISABLED)

return

try:

            all_items = os.listdir(self.current_dir)

            files = [f for f in all_items if os.path.isfile(os.path.join(self.current_dir, f))]

exceptExceptionas e:

            messagebox.showerror("错误"f"无法读取文件夹:{e}")

self.copy_btn.config(state=tk.DISABLED)

return

ifnot files:

self.status_label.config(text="文件夹中没有文件"fg="orange")

self.rename_btn.config(state=tk.DISABLED)

self.copy_btn.config(state=tk.DISABLED)

return

self.status_label.config(text=f"已加载 {len(files)} 个文件,可批量粘贴/复制"fg="green")

self.rename_btn.config(state=tk.NORMAL)

self.copy_btn.config(state=tk.NORMAL)

for i, fname inenumerate(files):

self.old_filenames.append(fname)

# 原文件名标签

            lbl = tk.Label(self.scrollable_frame, text=fname, width=35anchor="w"relief=tk.RIDGE)

            lbl.grid(row=i, column=0padx=5pady=2sticky="ew")

# 新文件名输入框,默认填入原文件名

            entry = tk.Entry(self.scrollable_frame, width=45)

            entry.insert(0, fname)

            entry.grid(row=i, column=1padx=5pady=2sticky="ew")

# 绑定 Ctrl+V 实现批量粘贴

            entry.bind("<Control-v>"self.paste_multiline)

self.entry_widgets.append(entry)

self.scrollable_frame.columnconfigure(0weight=1)

self.scrollable_frame.columnconfigure(1weight=2)

defpaste_multiline(selfevent):

"""在输入框中按 Ctrl+V 时触发:支持多行文本批量填充"""

        current_entry = event.widget

try:

            clip_text =self.root.clipboard_get()

except:

return

        lines = clip_text.splitlines()

        lines = [line.strip() for line in lines if line.strip()]

ifnot lines:

return

try:

            start_index =self.entry_widgets.index(current_entry)

exceptValueError:

return

for i, new_name inenumerate(lines):

            target_index = start_index + i

if target_index >=len(self.entry_widgets):

break

self.entry_widgets[target_index].delete(0, tk.END)

self.entry_widgets[target_index].insert(0, new_name)

        next_index = start_index +len(lines)

if next_index <len(self.entry_widgets):

self.entry_widgets[next_index].focus_set()

return"break"

defcopy_all_new_names(self):

"""复制所有新文件名(每行一个)到剪贴板"""

ifnotself.entry_widgets:

            messagebox.showinfo("提示""没有可复制的内容")

return

        new_names = [entry.get() for entry inself.entry_widgets]

        text_to_copy ="\n".join(new_names)

self.root.clipboard_clear()

self.root.clipboard_append(text_to_copy)

self.status_label.config(text=f"已复制 {len(new_names)} 个文件名到剪贴板"fg="green")

# 可选:短暂提示恢复

self.root.after(2000lambdaself.status_label.config(text="就绪"fg="blue"))

defrename_files(self):

ifnotself.current_dir:

            messagebox.showwarning("警告""请先选择一个文件夹")

return

# 收集新文件名并校验

        new_names = []

for entry inself.entry_widgets:

            new_name = entry.get().strip()

ifnot new_name:

                messagebox.showerror("错误""新文件名不能为空,请填写所有新文件名")

return

if'/'in new_name or'\\'in new_name:

                messagebox.showerror("错误"f"文件名不能包含路径分隔符:{new_name}")

return

            new_names.append(new_name)

iflen(set(new_names)) !=len(new_names):

            messagebox.showerror("错误""存在重复的新文件名,请确保每个新文件名唯一")

return

        all_files =set(os.listdir(self.current_dir))

        conflicts = []

for old, new inzip(self.old_filenames, new_names):

if new != old and new in all_files:

                conflicts.append(new)

if conflicts:

            messagebox.showerror("错误"f"以下新文件名已存在,请修改:\n"+"\n".join(conflicts))

return

        renamed_count =0

        errors = []

for old, new inzip(self.old_filenames, new_names):

if old == new:

continue

            old_path = os.path.join(self.current_dir, old)

            new_path = os.path.join(self.current_dir, new)

try:

                os.rename(old_path, new_path)

                renamed_count +=1

exceptExceptionas e:

                errors.append(f"{old} → {new} : {str(e)}")

if errors:

            messagebox.showerror("部分失败""\n".join(errors))

else:

            messagebox.showinfo("完成"f"成功重命名 {renamed_count} 个文件")

self.load_files()

self.status_label.config(text="重命名完成"fg="blue")

if__name__=="__main__":

    root = tk.Tk()

    app = BatchRenameApp(root)

    root.mainloop()