批量重命名

效果图:

bcd4316359634ee2be92c5bf09cb3aec.png

点击更多命名方式后,可以基于一般的两种命名方法进行格式化:

0a2c62bc07444e2d86ec12cb15706d7a.png

我原先还想添加配置保存功能和命名失败后撤回功能的,但后来发现实现起来不仅有一定难度,而且可能对命名的性能造成一定影响。

我注意看了一下别人有些命名程序支持替换掉原命名中存在的某个字啥的,但感觉这种需求确实太特殊了,故没有添加这种功能。

 Python源代码:

# -*- coding: utf-8 -*-
import os
import tkinter as tk
from re import findall, search, error
from tkinter import ttk
from tkinter import filedialog, messagebox, Radiobutton, StringVar


def get_files(directory):
    with os.scandir(directory) as entries:
        return [entry.name for entry in entries if entry.is_file()]


def show_default(param):
    try:
        prefix = int((entry_start_num.get())) - 1
    except (ValueError, TypeError):
        entry_start_num.delete(0, 'end')
        entry_start_num.insert(0, "1")
        prefix = param
    return prefix


def all_number_rename(directory, name_suffix, pre_concat, tail_concat):
    prefix = show_default(0) + 1
    files = temp_rename(directory)
    for old_name in files:
        new_name = f"{pre_concat}{prefix}{tail_concat}{name_suffix}"
        try:
            os.rename(old_name, new_name)   # 最终命名
        except Exception as e:
            messagebox.showerror(f'错误:{e},\n请尝试重新命名!')
        prefix += 1

    messagebox.showinfo("提示", "重命名成功!")


def prefix_suffix_rename(directory, name_suffix, pre_concat, tail_concat):
    # 初始化变量
    prev_get_time = 0
    time_interval = input_interval()
    prefix = show_default(0)
    suffix = 1
    folder_files = temp_rename(directory)

    for old_name in folder_files:
        get_time = os.path.getmtime(old_name)
        # 确定名字
        if (get_time - prev_get_time) > time_interval:
            suffix = 1
            prefix += 1
        else:
            suffix += 1

        new_name = f"{pre_concat}{prefix}-{suffix}{tail_concat}{name_suffix}"
        try:
            os.rename(old_name, new_name)
        except Exception as e:
            messagebox.showerror(f'错误:{e}\n请尝试重新命名!')
            return
        prev_get_time = get_time

    messagebox.showinfo("提示", "重命名成功!")


def temp_rename(director):
    random_bytes = os.urandom(4)
    random_num = int.from_bytes(random_bytes, signed=False, byteorder='big')
    temp_files = get_files(director)
    for index, temp in enumerate(temp_files, random_num):
        os.rename(temp, f'#temp{index}')
    temp_files = get_files(director)
    temp_files.sort(key=lambda x: os.path.getmtime(x))
    return temp_files


def input_interval():
    try:
        time_interval = float(entry_time_interval.get())
    except ValueError:
        entry_time_interval.delete(0, 'end')
        entry_time_interval.insert(0, '5')
        time_interval = 5
    return time_interval


def choose_directory():
    folder_selected = filedialog.askdirectory()
    if folder_selected:
        entry_dir.delete(0, 'end')
        entry_dir.insert(0, folder_selected)


def get_files_and_suffix():
    directory = entry_dir.get()
    try:
        if not get_files(directory):
            messagebox.showinfo("提示", "没有找到文件,请检查路径!")
            return
    except FileNotFoundError:
        messagebox.showerror("错误", "文件夹错误,请选择文件夹!")
        return
    os.chdir(directory)  # 改变文件路径,后续就不需要频繁的拼接路径了
    suffix = combobox.get()
    if not suffix or not suffix.startswith('.'):
        messagebox.showerror("错误", "请输入有效的文件后缀,且以点开头!")
        return
    mode = selected_option.get()
    head, tail = '', ''
    if mode == '3':
        global expression
        try:
            mode = search(r'{([12])}', expression).group(1)
            concat_list = findall(r'(.*?)\{[12]}(.*)', expression)[0]
            head, tail = concat_list
        except (AttributeError, error):
            messagebox.showerror('错误', '表达式出错, 请检查表达式!')
            return
    if mode == '1':
        prefix_suffix_rename(entry_dir.get(), suffix, head, tail)
    elif mode == '2':
        all_number_rename(entry_dir.get(), suffix, head, tail)
    else:
        messagebox.showerror('错误', '表达式出错, 请检查表达式!')
        return


def show_sub_window(expression):
    def destroy_sub_window(exp_entry):
        global expression
        expression = exp_entry.get()
        sub_window.destroy()

    sub_window = tk.Toplevel(root)
    sub_window.geometry('390x230+500+300')
    sub_window.resizable(False, False)
    sub_window.title("更多命名方式")
    info = tk.Label(sub_window, font=('宋体', 16), text="提示:{1}代表【前缀-后缀】命名\t\n     {2}代表【纯数字命名】\t\n"
                                     "eg: IMG{2} -> IMG1, IMG2, IMG3...\n   【{1}】 -> 【1-1】, 【1-2】...\n\n"
                                     "请输入你指定的命名格式:")

    expression_entry = tk.Entry(sub_window, width=40)
    expression_entry.insert(0, expression)
    expression_entry.place(relx=0.1, rely=0.6, relheight=0.15)
    info.place(relx=0, rely=0)
    close_button = tk.Button(sub_window, text="确定", bg="wheat",
                             command=lambda: destroy_sub_window(expression_entry))
    close_button.place(relx=0.4, rely=0.82, relheight=0.18, relwidth=0.2)


expression = ''
root = tk.Tk()
root.title("批量重命名工具")
root.geometry('390x230+500+300')
root.resizable(False, False)

entry_dir = tk.Entry(root, width=35)
entry_dir.place(relx=0.05, rely=0, relheight=0.13)

button_dir = tk.Button(root, text="选择文件夹", command=choose_directory, bg="wheat")
button_dir.place(relx=0.65, rely=0, relheight=0.13)

label_suffix = tk.Label(root, text="选择文件名后缀(可手动输入)", font=('宋体', 12, 'bold'))
label_suffix.place(relx=0.26, rely=0.17, relheight=0.13)

combobox = ttk.Combobox(root, values=['.jpg', '.png', '.jpeg', '.txt', '.json', '.xlsx', '.pdf', '.wps', '.docx'])
combobox.place(relx=0.05, rely=0.17, relwidth=0.2, relheight=0.13)

label_interval = tk.Label(root, text='<      s前缀相同', font=('宋体', 12, 'bold'))
label_interval.place(relx=0.6, rely=0.48, relheight=0.15)


entry_time_interval = tk.Entry(root, width=5)
entry_time_interval.place(relx=0.66, rely=0.48, relheight=0.15)

# 初始化两个复选框
selected_option = StringVar()
mode1 = Radiobutton(root, text='【前缀-后缀】命名', font=('宋体', 16), bg='gainsboro',
                    variable=selected_option, borderwidth=2, relief='groove', value=1)
mode2 = Radiobutton(root, text='【纯数字】命名   ', font=('宋体', 16), bg='gainsboro',
                    variable=selected_option, borderwidth=2, relief='groove', value=2)
mode3 = Radiobutton(root, text=' 更多命名方式    ',  relief='groove', bg='gainsboro',
                    variable=selected_option, font=('宋体', 16), value=3, command=lambda: show_sub_window(expression))
mode1.select()   # 默认情况下勾选第一个模式

mode1.place(relx=0.05, rely=0.48, relheight=0.16, relwidth=0.54)
mode2.place(relx=0.05, rely=0.65, relheight=0.16, relwidth=0.54)
mode3.place(relx=0.05, rely=0.82, relheight=0.16, relwidth=0.54)

label_start_num = tk.Label(root, text='命名起始数字:', font=('宋体', 16, 'bold'))
label_start_num.place(relx=0.05, rely=0.3, relheight=0.16)

entry_start_num = tk.Entry(root, width=10)
entry_start_num.place(relx=0.43, rely=0.32, relheight=0.13, relwidth=0.16)

button_rename = tk.Button(root, text="执行重命名", bg='cyan',     # 触发按钮,首先往get_files_and_suffix传递
                          font=('宋体', 20, 'bold'), command=get_files_and_suffix)
button_rename.place(relx=0.6, rely=0.65, relheight=0.35, relwidth=0.4)
root.mainloop()

为了使用方便 还用nuikta打包成了exe程序,试了一下打包成多文件有点大不知道为什么...

 

fuc* you 想上传个exe也上传不了,只能说这"C*dn"真是rubbish 啊,反正你也不审核是吧哈哈哈,rubbish editor

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值