Im trying to make a backup utility tool in python where the user can backup either folder or file but not both. The folder can backup folders but for the file, it does not backup the file. It will only produce a log file which state the starting time of backup process and the end time of backup process
import tkinter as tk
import tkinter.ttk as ttk
from tkinter import filedialog, messagebox
import shutil
import os
import time
import zipfile
def backup():
source_folders = source_folder_text.get('1.0', 'end').strip().split('\n')
dest_folder = dest_folder_text.get('1.0', 'end').strip()
if not source_folders:
messagebox.showerror('Error', 'Please specify at least one source folder.')
return
if not dest_folder:
messagebox.showerror('Error', 'Please specify a destination folder.')
return
is_file_selected = False
is_folder_selected = False
for source_folder in source_folders:
if os.path.isfile(source_folder):
is_file_selected = True
elif os.path.isdir(source_folder):
is_folder_selected = True
if is_file_selected and is_folder_selected:
messagebox.showerror('Error', 'Please select either files or folders for backup, not both.')
return
try:
if not os.path.exists(dest_folder):
os.makedirs(dest_folder)
timestamp = time.strftime('%Y%m%d-%H%M%S')
backup_folder = os.path.join(dest_folder, f'backup-{timestamp}')
if not os.path.exists(backup_folder):
os.makedirs(backup_folder)
log_file = os.path.join(backup_folder, 'backup.log')
with open(log_file, 'w') as f:
f.write(f'Backup started at {time.strftime("%Y-%m-%d %H:%M:%S")}\n')
total_files = 0
for source_folder in source_folders:
for root, dirs, files in os.walk(source_folder):
total_files += len(files)
progress_window = tk.Toplevel()
progress_window.title('Backup Progress')
progress_label = tk.Label(progress_window, text='Backing up files...')
progress_label.pack()
progress_bar = tk.ttk.Progressbar(progress_window, orient='horizontal', length=300, mode='determinate', maximum=total_files)
progress_bar.pack()
current_file = 0
for source_folder in source_folders:
for root, dirs, files in os.walk(source_folder):
for file in files:
source_file = os.path.join(root, file)
dest_file = os.path.join(backup_folder, os.path.relpath(source_file, source_folder))
dest_dir = os.path.dirname(dest_file)
if not os.path.exists(dest_dir):
os.makedirs(dest_dir)
if os.path.exists(dest_file) and os.path.getmtime(dest_file) >= os.path.getmtime(source_file):
# skip if destination file already exists and is newer than source file
with open(log_file, 'a') as f:
f.write(f'[SKIP] {source_file} (already exists)\n')
else:
shutil.copy2(source_file, dest_file)
with open(log_file, 'a') as f:
f.write(f'[COPY] {source_file} to {dest_file}\n')
current_file += 1
progress_bar['value'] = current_file
progress_label.config(text=f'Backing up {source_file}...')
progress_window.update()
with open(log_file, 'a') as f:
f.write(f'Backup completed at {time.strftime("%Y-%m-%d %H:%M:%S")}\n')
if compress_var.get():
progress_label.config(text='Compressing backup files...')
zip_file = os.path.join(dest_folder, f'backup-{timestamp}.zip')
with zipfile.ZipFile(zip_file, 'w', zipfile.ZIP_DEFLATED) as zipf:
for root, dirs, files in os.walk(backup_folder):
for file in files:
zipf.write(os.path.join(root, file), os.path.relpath(os.path.join(root, file), backup_folder))
shutil.rmtree(backup_folder)
messagebox.showinfo('Success', 'Backup completed successfully.')
clear()
except Exception as e:
with open(log_file, 'a') as f:
f.write(f'[ERROR] An error occurred during backup: {str(e)}\n')
messagebox.showerror('Error', f'An error occurred during backup:\n{str(e)}')
def browse_source_folder():
folder = filedialog.askdirectory()
if folder:
source_folder_text.insert('end', folder + '\n')
def browse_source_file():
file = filedialog.askopenfilename()
if file:
source_folder_text.insert('end', file + '\n')
def browse_dest_folder():
folder = filedialog.askdirectory()
if folder:
dest_folder_text.delete('1.0', 'end')
dest_folder_text.insert('1.0', folder)
def clear():
source_folder_text.delete('1.0', 'end')
dest_folder_text.delete('1.0', 'end')
compress_var.set(False)
# Create the main window
root = tk.Tk()
root.title('Backup Tool')
root.geometry('820x400')
root.config(bg='#FFFFFF')
# Create the source folder section
source_folder_label = tk.Label(root, text='Source folders or files:', font=('Helvetica', 12, 'bold'), bg='#FFFFFF')
source_folder_label.pack(pady=10)
source_folder_text = tk.Text(root, height=5)
source_folder_text.pack()
select_folder_or_file_label = tk.Label(root, text='Select either a folder or a file for backup, but not both.', font=('TkDefaultFont', 10), fg='red', bg='#FFFFFF')
select_folder_or_file_label.pack(pady=5)
source_folder_button_frame = tk.Frame(root, bg='#FFFFFF')
source_folder_button_frame.pack(pady=5)
browse_source_folder_button = tk.Button(source_folder_button_frame, text='Browse Folder', command=browse_source_folder, font=('Helvetica', 10))
browse_source_folder_button.pack(side='left', padx=10)
browse_source_file_button = tk.Button(source_folder_button_frame, text='Browse File', command=browse_source_file, font=('Helvetica', 10))
browse_source_file_button.pack(side='left')
# Create the destination folder section
dest_folder_frame = tk.Frame(root, bg='#FFFFFF')
dest_folder_frame.pack(pady=10)
dest_folder_label = tk.Label(dest_folder_frame, text='Destination folder:', font=('Helvetica', 12, 'bold'), bg='#FFFFFF')
dest_folder_label.pack(side='left', padx=10)
dest_folder_text = tk.Text(dest_folder_frame, height=1, font=('Helvetica', 10))
dest_folder_text.pack(side='left')
browse_dest_folder_button = tk.Button(dest_folder_frame, text='Browse', command=browse_dest_folder, font=('Helvetica', 10))
browse_dest_folder_button.pack(side='left', padx=10)
# Create the backup and compression section
compress_checkbox_frame = tk.Frame(root, bg='#FFFFFF')
compress_checkbox_frame.pack(pady=10)
compress_var = tk.BooleanVar()
compress_checkbox = tk.Checkbutton(compress_checkbox_frame, text='Compress backup files', variable=compress_var, bg='#FFFFFF')
compress_checkbox.pack(side='left', padx=10)
clear_button = tk.Button(compress_checkbox_frame, text='Clear', command=clear, font=('Helvetica', 10))
clear_button.pack(side='left')
backup_button = tk.Button(root, text='Backup', command=backup, font=('Helvetica', 12, 'bold'))
backup_button.pack(pady=10)
# Start the main event loop
root.mainloop()
I tried modify it but im stuck