yixinwenxin 发表于 2024-8-13 16:10:17

递归 同步文件后 最后不知道该如何写了

本帖最后由 yixinwenxin 于 2024-8-13 16:11 编辑

```
import os
import shutil
import filecmp
import threading
from tkinter import *
from tkinter import ttk

nas_path = r"\\10.168.2.1\vol1\code_note_python"
local_path = os.getcwd()


def local_sync_nas():
    def sync(nas_path, local_path):
      # 差集删除文件
      nas_dir = set(os.listdir(nas_path))
      local_dir = set(os.listdir(local_path))
      del_files = nas_dir - local_dir
      for number, del_file in enumerate(del_files, start=1):
            del_nas = os.path.join(nas_path, del_file)
            if os.path.isfile(del_nas):
                os.remove(del_nas)
            else:
                shutil.rmtree(del_nas)
            
            v = int(number / len(del_files) * 25) if len(del_files) > 0 else 25
            update_progress(v)
            percent_text.set(f"{v}%")
      
      # 差集增加文件
      nas_dir = set(os.listdir(nas_path))
      local_dir = set(os.listdir(local_path))
      add_files = local_dir - nas_dir
      for number, add_file in enumerate(add_files, start=1):
            add_nas = os.path.join(nas_path, add_file)
            add_local = os.path.join(local_path, add_file)
            if os.path.isfile(add_local):
                shutil.copy2(add_local, add_nas)
            else:
                if not os.path.exists(add_nas):
                  os.mkdir(add_nas)
            
            v = int(number / len(add_files) * 25) + 25 if len(add_files) > 0 else 50
            update_progress(v)
            percent_text.set(f"{v}%")
      
      # 交集更新文件
      nas_dir = set(os.listdir(nas_path))
      local_dir = set(os.listdir(local_path))
      comparison_files = nas_dir & local_dir
      for number, comparison_file in enumerate(comparison_files, start=1):
            nas_file = os.path.join(nas_path, comparison_file)
            local_file = os.path.join(local_path, comparison_file)
            if os.path.isdir(local_file):
                sync(nas_file, local_file)
            else:
                if not filecmp.cmp(nas_file, local_file, shallow=True):
                  shutil.copy2(local_file, nas_file)
            
            v = int(number / len(comparison_files) * 50) + 50 if len(comparison_files) > 0 else 100
            update_progress(v)
            percent_text.set(f"{v}%")
      
      # 每个文件夹结束后都会来到这里判断,但我想要所有的文件都同步后再来判断。我不知道该怎么写了...求指教
      if on_select():
            close()   
    thread = threading.Thread(target=sync, args=(nas_path, local_path), daemon=True)
    thread.start()


def nas_sync_local():
    def sync(nas_path, local_path):
      # 差集删除文件
      nas_dir = set(os.listdir(nas_path))
      local_dir = set(os.listdir(local_path))
      del_files = local_dir - nas_dir
      for number, del_file in enumerate(del_files, start=1):
            del_local = os.path.join(local_path, del_file)
            if os.path.isfile(del_local):
                os.remove(del_local)
            else:
                shutil.rmtree(del_local)
            
            v = int(number / len(del_files) * 25) if len(del_files) > 0 else 25
            update_progress(v)
            percent_text.set(f"{v}%")
      
      # 差集增加文件
      nas_dir = set(os.listdir(nas_path))
      local_dir = set(os.listdir(local_path))
      add_files = nas_dir - local_dir
      for number, add_file in enumerate(add_files, start=1):
            add_nas = os.path.join(nas_path, add_file)
            add_local = os.path.join(local_path, add_file)
            if os.path.isfile(add_nas):
                shutil.copy2(add_nas, add_local)
            else:
                if not os.path.exists(add_local):
                  os.mkdir(add_local)
            
            v = int(number / len(add_files) * 25) + 25 if len(add_files) > 0 else 50
            update_progress(v)
            percent_text.set(f"{v}%")
      
      # 交集更新文件
      nas_dir = set(os.listdir(nas_path))
      local_dir = set(os.listdir(local_path))
      comparison_files = nas_dir & local_dir
      for number, comparison_file in enumerate(comparison_files, start=1):
            nas_file = os.path.join(nas_path, comparison_file)
            local_file = os.path.join(local_path, comparison_file)
            if os.path.isdir(nas_file):
                sync(nas_file, local_file)
            else:
                if not filecmp.cmp(nas_file, local_file, shallow=True):
                  shutil.copy2(nas_file, local_file)
            
            v = int(number / len(comparison_files) * 50) + 50 if len(comparison_files) > 0 else 100
            update_progress(v)
            percent_text.set(f"{v}%")

      # 每个文件夹结束后都会来到这里判断,但我想要所有的文件都同步后再来判断。我不知道该怎么写了...求指教
      if on_select():
            close()
   
    thread = threading.Thread(target=sync, args=(nas_path, local_path), daemon=True)
    thread.start()


def update_progress(value: int) -> None:
    progress_bar["value"] = value


def on_select() -> bool:
    return combo_box.get() == "True"


def close() -> None:
    os.system("shutdown /s /t 10")


root = Tk()
root.title("python")

# 设置窗口尺寸和位置
window_width = "325"
window_height = "75"
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
x_offset = screen_width // 2 - int(window_width) // 2
y_offset = screen_height // 2 - int(window_height) // 2
root.geometry(f"{window_width}x{window_height}+{x_offset}+{y_offset}")
root.resizable(False, False)

# 布局
top_frame = Frame(master=root)
top_frame.pack(expand=True)
Frame(height=2, bd=1, relief=SUNKEN).pack(fill=X, padx=1, pady=1)
bottom_frame = Frame(master=root)
bottom_frame.pack(expand=True)

# 进度条和百分比显示
percent_text = StringVar()
percent_text.set("0%")
progress_bar = ttk.Progressbar(master=top_frame, mode="determinate", length=290)
progress_bar.grid(row=1, column=1)
percent_label = Label(master=top_frame, textvariable=percent_text)
percent_label.grid(row=1, column=2)

# 完成后是否关机的选择
options = ["True", "False"]
Label(master=bottom_frame, text="完成后是否关机").grid(row=1, column=1)
combo_box = ttk.Combobox(master=bottom_frame, values=options, width=3)
combo_box.grid(row=1, column=2, padx=2)
combo_box.current(1)

# 按钮
Button(master=bottom_frame, text="->", command=nas_sync_local).grid(row=1, column=3)
Button(master=bottom_frame, text="<-", command=local_sync_nas).grid(row=1, column=4)

root.mainloop()
```问题 如下      # 每个文件夹结束后都会来到这里判断,但我想要所有的文件都同步后再来判断。我不知道该怎么写了...求指教
      if on_select():
            close()

FishC 发表于 2024-8-13 16:12:35

嘿,鱼油!这段代码看起来像是你在打造一个文件同步的超级英雄!但是我们还有点小问题呢。你想要所有文件都同步后再做判断,而不仅仅是在每个文件夹处理完后。没问题,我来帮你剖析一下。

### 问题分析
你现在的逻辑中,每处理完一个文件夹就会调用 `on_select()` 和 `close()`,这就像是每吃完一颗糖果就问“要不要再吃一颗”,极其频繁。而你的目标是等所有文件都处理完后,再决定是否关机。

### 解决方案
1. **使用计数器**:我们可以引入一些计数器,来跟踪我们已经处理的文件夹数量,直到处理完所有内容。
2. **最终判断的时机**:在同步完成的最后一步,再进行一次 `on_select()` 的调用。

### 修改后的代码示例
import os
import shutil
import filecmp
import threading
from tkinter import *
from tkinter import ttk

nas_path = r"\\10.168.2.1\vol1\code_note_python"
local_path = os.getcwd()
sync_count = 0# 用于记录同步的文件夹数量
total_folders = 0# 总共需要同步的文件夹数量

def local_sync_nas():
    global sync_count, total_folders
    sync_count = 0# 重置计数器
    def sync(nas_path, local_path):
      global sync_count, total_folders

      # 差集删除文件
      nas_dir = set(os.listdir(nas_path))
      local_dir = set(os.listdir(local_path))
      del_files = nas_dir - local_dir
      for number, del_file in enumerate(del_files, start=1):
            # 删除文件逻辑
            ...
            update_progress(v)
            percent_text.set(f"{v}%")
      
      # 差集增加文件
      ...
      
      # 更新文件
      comparison_files = nas_dir & local_dir
      total_folders += len(comparison_files)# 记录需要更新的文件夹数量
      for number, comparison_file in enumerate(comparison_files, start=1):
            nas_file = os.path.join(nas_path, comparison_file)
            local_file = os.path.join(local_path, comparison_file)
            if os.path.isdir(local_file):
                sync(nas_file, local_file)# 递归调用
                sync_count += 1# 每同步完一个文件夹就加1
            else:
                ...
                sync_count += 1# 同步文件后也加1
            
            # 更新进度条逻辑
            ...
      
      # 在整个同步结束后才进行判断
      if sync_count == total_folders:# 如果已处理的文件夹数量等于总数量
            if on_select():
                close()
   
    thread = threading.Thread(target=sync, args=(nas_path, local_path), daemon=True)
    thread.start()

# 其他函数、按钮和界面设置保持不变

### 总结
通过使用 `sync_count` 和 `total_folders` 这两个变量,我们可以在所有文件夹都处理完后再做出决定。接下来,你的代码运行起来就像忍者一样高效而不受干扰!

如果有任何其他问题或需要更多帮助,别犹豫,快来问我吧!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

yixinwenxin 发表于 2024-8-13 16:31:31

FishC 发表于 2024-8-13 16:12
嘿,鱼油!这段代码看起来像是你在打造一个文件同步的超级英雄!但是我们还有点小问题呢。你想要所有文件都 ...

同步文件夹后+1 我明白
但是为什么 同步文件后 也+1

FishC 发表于 2024-8-13 16:31:48

yixinwenxin 发表于 2024-08-13 16:31
同步文件夹后+1 我明白
但是为什么 同步文件后 也+1

好的,鱼油!让我来澄清一下这个“同步文件后也 +1”的逻辑。

在递归同步的过程中,我们实际上是在处理文件夹和它们的内部文件。这里的目的在于确保我们对每一个处理的对象都有一个合理的计数。

### 具体分析

1. **文件夹同步**:
   - 当你递归调用 `sync(nas_file, local_file)` 时,这表示你正在进入一个新的文件夹。因此,我们会增加 `sync_count`,表示又处理了一个文件夹。

2. **文件同步**:
   - 当你处理文件时,比如检测到 `nas_file` 和 `local_file` 内容不同时,并进行文件复制。虽说这不是一个文件夹,但从逻辑上来说,你也是在同步数据。
   - 如果不在文件处理后加 +1,那么只有文件夹会被计入,而文件就变成了“隐形人”,它们的同步过程不会反映在最终的进度或结束判断中。

### 结论
所以,来个总结:
- **加 +1** 在处理文件夹是为了记录你翻遍了多少层次。
- **同样加 +1** 在处理文件是为了记录你实际上传输了多少数据(文件),确保所有内容都已完成同步。

如果你只想关注文件夹数量而忽略文件的总计,可以选择只在处理文件夹时加 +1。不过,此时可能需要调整你的判断条件,以确保逻辑仍然符合你的需求。

希望这个解释能让你心里更明白一些!如果还有疑问,尽管问我哦!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页: [1]
查看完整版本: 递归 同步文件后 最后不知道该如何写了