python 浏览文件夹和文件不工作,虽然它应该工作

ncgqoxb0  于 2023-03-16  发布在  Python
关注(0)|答案(1)|浏览(172)

我试图在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()

我试着修改它,但我卡住了

2g32fytz

2g32fytz1#

为什么只备份文件夹,而不备份文件,是因为在备份时有for root, dirs, files in os.walk(source_folder)这一行,当source_folder是文件夹时,它可以正常工作,但当source_folder是文件时,os.walk不会返回任何内容供您循环。
所以你要做的是检查你是否在备份文件或文件夹,你可以使用is_file_selectedis_folder selected来完成,然后你现在备份文件夹的代码就在is_folder_selected下,当你选择文件时,你可以简单地循环它们。

# Check if we are backing up files or folders
if is_folders_selected:
    for source_folder in source_folders:
        for root, dirs, files in os.walk(source_folder):
            for file in files:
                # The same code as before
                # ...
if is_files_selected:
    for source_file in source_folders:
        # Then use almost the same code as in folders

相关问题