Skip to content

Commit ea9aec0

Browse files
authored
Create File-Renamer.py
1 parent 7b81198 commit ea9aec0

1 file changed

Lines changed: 194 additions & 0 deletions

File tree

21-File-renamer/File-Renamer.py

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
import tkinter as tk
2+
from tkinter import filedialog, messagebox
3+
import os
4+
from copy import deepcopy
5+
6+
class FileRenamerApp:
7+
def __init__(self, root):
8+
self.root = root
9+
self.root.title("File Renamer")
10+
self.root.geometry("700x700")
11+
self.root.configure(bg="#1f2f3a")
12+
self.root.resizable(False, False)
13+
14+
self.folder_path = ""
15+
self.files = []
16+
self.original_files = []
17+
self.preview_files = []
18+
19+
self.create_ui()
20+
21+
def create_ui(self):
22+
# Title
23+
tk.Label(self.root, text="File Renamer", font=("Helvetica", 28, "bold"),
24+
bg="#1f2f3a", fg="#ffffff").pack(pady=20)
25+
26+
# Folder selection
27+
folder_frame = tk.Frame(self.root, bg="#1f2f3a")
28+
folder_frame.pack(pady=10, fill="x", padx=20)
29+
tk.Label(folder_frame, text="Select Folder:", font=("Helvetica", 12),
30+
bg="#1f2f3a", fg="#bdc3c7").pack(anchor="w")
31+
self.folder_entry = tk.Entry(folder_frame, font=("Helvetica", 14), bd=0,
32+
highlightthickness=2, highlightbackground="#2980b9", width=50)
33+
self.folder_entry.pack(side="left", pady=5, ipady=6)
34+
tk.Button(folder_frame, text="Browse", command=self.browse_folder,
35+
bg="#2980b9", fg="white", font=("Helvetica", 12, "bold"), bd=0,
36+
width=10, height=2, activebackground="#3498db", cursor="hand2").pack(side="left", padx=5)
37+
38+
# Options frame
39+
options_frame = tk.Frame(self.root, bg="#1f2f3a")
40+
options_frame.pack(pady=10, fill="x", padx=20)
41+
42+
options_frame = tk.Frame(self.root, bg="#1f2f3a")
43+
options_frame.pack(pady=10, fill="x", padx=20)
44+
45+
# Row 0: Prefix and Suffix
46+
tk.Label(options_frame, text="Prefix:", font=("Helvetica", 12), bg="#1f2f3a", fg="#bdc3c7").grid(row=0, column=0, sticky="w")
47+
self.prefix_entry = tk.Entry(options_frame, font=("Helvetica", 12), bd=0,
48+
highlightthickness=2, highlightbackground="#27ae60", width=25)
49+
self.prefix_entry.grid(row=0, column=1, pady=5, padx=5, ipady=4)
50+
51+
tk.Label(options_frame, text="Suffix:", font=("Helvetica", 12), bg="#1f2f3a", fg="#bdc3c7").grid(row=0, column=2, sticky="w")
52+
self.suffix_entry = tk.Entry(options_frame, font=("Helvetica", 12), bd=0,
53+
highlightthickness=2, highlightbackground="#27ae60", width=25)
54+
self.suffix_entry.grid(row=0, column=3, pady=5, padx=5, ipady=4)
55+
56+
# Row 1: Find and Replace
57+
tk.Label(options_frame, text="Find:", font=("Helvetica", 12), bg="#1f2f3a", fg="#bdc3c7").grid(row=1, column=0, sticky="w")
58+
self.find_entry = tk.Entry(options_frame, font=("Helvetica", 12), bd=0,
59+
highlightthickness=2, highlightbackground="#27ae60", width=25)
60+
self.find_entry.grid(row=1, column=1, pady=5, padx=5, ipady=4)
61+
62+
tk.Label(options_frame, text="Replace:", font=("Helvetica", 12), bg="#1f2f3a", fg="#bdc3c7").grid(row=1, column=2, sticky="w")
63+
self.replace_entry = tk.Entry(options_frame, font=("Helvetica", 12), bd=0,
64+
highlightthickness=2, highlightbackground="#27ae60", width=25)
65+
self.replace_entry.grid(row=1, column=3, pady=5, padx=5, ipady=4)
66+
67+
# Preview frame
68+
preview_frame = tk.Frame(self.root, bg="#1f2f3a")
69+
preview_frame.pack(pady=10, fill="both", expand=True, padx=20)
70+
tk.Label(preview_frame, text="Preview Files:", font=("Helvetica", 12), bg="#1f2f3a", fg="#bdc3c7").pack(anchor="w")
71+
72+
self.preview_listbox = tk.Listbox(preview_frame, font=("Helvetica", 12), bg="#2c3e50",
73+
fg="white", selectbackground="#2980b9", selectforeground="white")
74+
self.preview_listbox.pack(fill="both", expand=True, pady=5)
75+
scrollbar = tk.Scrollbar(self.preview_listbox, orient="vertical")
76+
scrollbar.pack(side="right", fill="y")
77+
self.preview_listbox.config(yscrollcommand=scrollbar.set)
78+
scrollbar.config(command=self.preview_listbox.yview)
79+
80+
# Buttons frame
81+
btn_frame = tk.Frame(self.root, bg="#1f2f3a")
82+
btn_frame.pack(pady=15)
83+
84+
tk.Button(btn_frame, text="Preview Changes", command=self.preview_changes,
85+
bg="#2980b9", fg="white", font=("Helvetica", 12, "bold"),
86+
width=20, height=2, bd=0, activebackground="#3498db", cursor="hand2").grid(row=0, column=0, padx=10)
87+
88+
tk.Button(btn_frame, text="Rename Files", command=self.rename_files,
89+
bg="#27ae60", fg="white", font=("Helvetica", 12, "bold"),
90+
width=20, height=2, bd=0, activebackground="#2ecc71", cursor="hand2").grid(row=0, column=1, padx=10)
91+
92+
tk.Button(btn_frame, text="Undo", command=self.undo_rename,
93+
bg="#e67e22", fg="white", font=("Helvetica", 12, "bold"),
94+
width=20, height=2, bd=0, activebackground="#f39c12", cursor="hand2").grid(row=0, column=2, padx=10)
95+
96+
def browse_folder(self):
97+
path = filedialog.askdirectory()
98+
if path:
99+
self.folder_path = path
100+
self.folder_entry.delete(0, tk.END)
101+
self.folder_entry.insert(0, path)
102+
self.load_files()
103+
104+
def load_files(self):
105+
self.files = []
106+
self.original_files = []
107+
self.preview_files = []
108+
self.preview_listbox.delete(0, tk.END)
109+
for f in os.listdir(self.folder_path):
110+
full_path = os.path.join(self.folder_path, f)
111+
if os.path.isfile(full_path):
112+
self.files.append(f)
113+
self.original_files = deepcopy(self.files)
114+
self.update_preview_list(self.files)
115+
116+
def update_preview_list(self, file_list):
117+
self.preview_listbox.delete(0, tk.END)
118+
for f in file_list:
119+
self.preview_listbox.insert(tk.END, f)
120+
121+
def preview_changes(self):
122+
if not self.files:
123+
messagebox.showerror("Error", "No files to preview.")
124+
return
125+
126+
prefix = self.prefix_entry.get()
127+
suffix = self.suffix_entry.get()
128+
find_text = self.find_entry.get()
129+
replace_text = self.replace_entry.get()
130+
131+
self.preview_files = []
132+
for filename in self.files:
133+
new_name = filename
134+
if find_text:
135+
new_name = new_name.replace(find_text, replace_text)
136+
if prefix:
137+
new_name = prefix + new_name
138+
if suffix:
139+
name, ext = os.path.splitext(new_name)
140+
new_name = name + suffix + ext
141+
self.preview_files.append(new_name)
142+
143+
self.update_preview_list(self.preview_files)
144+
145+
def rename_files(self):
146+
if not self.preview_files:
147+
messagebox.showerror("Error", "Please preview changes first!")
148+
return
149+
150+
confirm = messagebox.askyesno("Confirm", "Are you sure you want to rename all files?")
151+
if not confirm:
152+
return
153+
154+
try:
155+
self.last_rename = [] # reset last rename
156+
for old_name, new_name in zip(self.original_files, self.preview_files):
157+
old_path = os.path.join(self.folder_path, old_name)
158+
new_path = os.path.join(self.folder_path, new_name)
159+
if old_name != new_name:
160+
os.rename(old_path, new_path)
161+
self.last_rename.append((new_name, old_name)) # store for undo
162+
163+
messagebox.showinfo("Success", "Files renamed successfully!")
164+
self.load_files()
165+
except Exception as e:
166+
messagebox.showerror("Error", f"Failed to rename files: {e}")
167+
168+
def undo_rename(self):
169+
if not hasattr(self, "last_rename") or not self.last_rename:
170+
messagebox.showerror("Error", "No rename actions to undo.")
171+
return
172+
173+
confirm = messagebox.askyesno("Undo", "Are you sure you want to undo the last rename?")
174+
if not confirm:
175+
return
176+
177+
try:
178+
for current_name, original_name in self.last_rename:
179+
current_path = os.path.join(self.folder_path, current_name)
180+
original_path = os.path.join(self.folder_path, original_name)
181+
if os.path.exists(current_path):
182+
os.rename(current_path, original_path)
183+
184+
messagebox.showinfo("Success", "Undo successful!")
185+
self.load_files()
186+
self.last_rename = [] # clear after undo
187+
except Exception as e:
188+
messagebox.showerror("Error", f"Failed to undo rename: {e}")
189+
190+
191+
if __name__ == "__main__":
192+
root = tk.Tk()
193+
app = FileRenamerApp(root)
194+
root.mainloop()

0 commit comments

Comments
 (0)