我试图在python中做一个备份工具,用户可以备份文件夹或文件,但不能同时备份。文件夹可以备份文件夹,但对于文件,它不备份文件。它只会产生一个日志文件,状态备份过程的开始时间和备份过程的结束时间
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()
我试着修改它,但我卡住了
1条答案
按热度按时间2g32fytz1#
为什么只备份文件夹,而不备份文件,是因为在备份时有
for root, dirs, files in os.walk(source_folder)
这一行,当source_folder
是文件夹时,它可以正常工作,但当source_folder
是文件时,os.walk
不会返回任何内容供您循环。所以你要做的是检查你是否在备份文件或文件夹,你可以使用
is_file_selected
和is_folder selected
来完成,然后你现在备份文件夹的代码就在is_folder_selected
下,当你选择文件时,你可以简单地循环它们。