使用python复制目录以及目录的子目录的文件到脚本运行的目录(工具+源码)

目录

不带ui界面的

整体思路

带ui界面的

整体思路

指定目录的复制

小工具下载地址


不带ui界面的

python 复制代码
import os
import shutil




def copy_files_to_root(target_dirs):
    """
    将多个指定目录下的所有文件(包括子目录)复制到当前脚本的根目录,
    所有文件平铺到以源目录名命名的文件夹中(无嵌套子目录)

    Args:
        target_dirs (list): 要复制的源目录路径列表
    """
    # 获取当前脚本的根目录(即运行该py文件的目录)
    script_root = os.path.dirname(os.path.abspath(__file__))
    print(f"脚本根目录: {script_root}\n")

    # 遍历每个目标目录
    for target_dir in target_dirs:
        # 检查源目录是否存在
        if not os.path.isdir(target_dir):
            print(f"⚠️  错误:源目录 {target_dir} 不存在,跳过该目录!")
            continue

        # 获取源目录的名称(作为根目录下的目标文件夹名)
        dir_name = os.path.basename(os.path.normpath(target_dir))
        # 最终目标文件夹(脚本根目录 + 源目录名)
        dest_root = os.path.join(script_root, dir_name)
        # 创建目标文件夹(不存在则创建)
        os.makedirs(dest_root, exist_ok=True)

        print(f"🔄 开始复制目录:{target_dir} -> {dest_root}(所有文件平铺)")

        # 遍历源目录下的所有文件(包括子目录)
        for root, dirs, files in os.walk(target_dir):
            # 复制当前目录下的所有文件(直接放到目标根文件夹)
            for file in files:
                # 源文件完整路径
                src_file = os.path.join(root, file)
                # 初始目标文件路径(平铺到目标根文件夹)
                dest_file = os.path.join(dest_root, file)

                # 处理重名文件:如果文件已存在,自动添加序号(如 file.txt -> file_1.txt)
                counter = 1
                while os.path.exists(dest_file):
                    file_name, file_ext = os.path.splitext(file)
                    dest_file = os.path.join(dest_root, f"{file_name}_{counter}{file_ext}")
                    counter += 1

                # 复制文件
                try:
                    shutil.copy2(src_file, dest_file)
                    print(f"✅ 已复制: {src_file} -> {dest_file}")
                except Exception as e:
                    print(f"❌ 复制失败: {src_file} 原因: {e}")
        print(f"✅ 目录 {target_dir} 复制完成!\n")


if __name__ == "__main__":
    # 传入多个目录路径的数组(列表)
    target_directories = [
        r"E:\test\a",  # 第一个要复制的目录
        r"E:\test\b",  # 第二个要复制的目录
        r"E:\test\c",  # 第二个要复制的目录

    ]

    # 执行复制操作
    copy_files_to_root(target_directories)
    print("📚 所有指定目录的文件复制完成!")

整体思路

  1. 遍历目录以及子目录的文件
复制代码
获取源目录的名称
复制代码
创建存放结果目标文件夹(不存在则创建)
  1. 将遍历的文件复制到脚本运行目录

带ui界面的

python 复制代码
import os
import shutil
import tkinter as tk
from tkinter import ttk, filedialog, messagebox


class FileCopyGUI:
    def __init__(self, root):
        self.root = root
        self.root.title("文件批量复制工具")
        self.root.geometry("700x500")  # 窗口大小

        # 存储选中的源目录列表
        self.selected_dirs = []

        # 创建UI组件
        self._create_widgets()

    def _create_widgets(self):
        # 1. 目录选择区域
        frame_select = ttk.LabelFrame(self.root, text="选择要复制的目录")
        frame_select.pack(padx=10, pady=10, fill=tk.X)

        # 选择目录按钮
        btn_add_dir = ttk.Button(frame_select, text="添加目录", command=self.add_directory)
        btn_add_dir.pack(side=tk.LEFT, padx=10, pady=5)

        # 清空目录按钮
        btn_clear_dirs = ttk.Button(frame_select, text="清空列表", command=self.clear_directories)
        btn_clear_dirs.pack(side=tk.LEFT, padx=5, pady=5)

        # 目录列表展示
        self.dir_listbox = tk.Listbox(frame_select, height=8, width=80)
        self.dir_listbox.pack(side=tk.LEFT, padx=10, pady=5, fill=tk.X, expand=True)

        # 滚动条
        scrollbar = ttk.Scrollbar(frame_select, orient=tk.VERTICAL, command=self.dir_listbox.yview)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y, pady=5)
        self.dir_listbox.config(yscrollcommand=scrollbar.set)

        # 2. 操作按钮区域
        frame_operate = ttk.Frame(self.root)
        frame_operate.pack(padx=10, pady=5, fill=tk.X)

        btn_copy = ttk.Button(frame_operate, text="开始复制", command=self.start_copy, style="Accent.TButton")
        btn_copy.pack(side=tk.LEFT, padx=10, pady=5)

        # 3. 日志输出区域
        frame_log = ttk.LabelFrame(self.root, text="复制日志")
        frame_log.pack(padx=10, pady=10, fill=tk.BOTH, expand=True)

        # 日志文本框
        self.log_text = tk.Text(frame_log, height=15, wrap=tk.WORD)
        self.log_text.pack(side=tk.LEFT, padx=10, pady=5, fill=tk.BOTH, expand=True)

        # 日志滚动条
        log_scrollbar = ttk.Scrollbar(frame_log, orient=tk.VERTICAL, command=self.log_text.yview)
        log_scrollbar.pack(side=tk.RIGHT, fill=tk.Y, pady=5)
        self.log_text.config(yscrollcommand=log_scrollbar.set)

        # 设置文本框只读
        self.log_text.config(state=tk.DISABLED)

    def add_directory(self):
        """添加选中的目录到列表"""
        dir_path = filedialog.askdirectory(title="选择要复制的目录")
        if dir_path and dir_path not in self.selected_dirs:
            self.selected_dirs.append(dir_path)
            self.dir_listbox.insert(tk.END, dir_path)
            self._log(f"已添加目录:{dir_path}")

    def clear_directories(self):
        """清空选中的目录列表"""
        self.selected_dirs.clear()
        self.dir_listbox.delete(0, tk.END)
        self._log("已清空目录列表")

    def _log(self, message):
        """在日志框中输出信息"""
        self.log_text.config(state=tk.NORMAL)
        self.log_text.insert(tk.END, f"{message}\n")
        self.log_text.see(tk.END)  # 自动滚动到最后一行
        self.log_text.config(state=tk.DISABLED)
        self.root.update_idletasks()  # 实时刷新界面

    def start_copy(self):
        """执行文件复制操作"""
        if not self.selected_dirs:
            messagebox.showwarning("警告", "请先添加要复制的目录!")
            return

        # 获取脚本根目录
        script_root = os.path.dirname(os.path.abspath(__file__))
        self._log(f"===== 开始复制 =====")
        self._log(f"脚本根目录:{script_root}")

        # 遍历每个选中的目录
        for target_dir in self.selected_dirs:
            if not os.path.isdir(target_dir):
                self._log(f"⚠️  错误:目录 {target_dir} 不存在,跳过!")
                continue

            # 目标文件夹(脚本根目录/源目录名)
            dir_name = os.path.basename(os.path.normpath(target_dir))
            dest_root = os.path.join(script_root, dir_name)
            os.makedirs(dest_root, exist_ok=True)
            self._log(f"\n🔄 处理目录:{target_dir} -> {dest_root}(文件平铺)")

            # 遍历所有文件并复制
            file_count = 0
            for root, dirs, files in os.walk(target_dir):
                for file in files:
                    src_file = os.path.join(root, file)
                    dest_file = os.path.join(dest_root, file)

                    # 处理重名文件
                    counter = 1
                    while os.path.exists(dest_file):
                        file_name, ext = os.path.splitext(file)
                        dest_file = os.path.join(dest_root, f"{file_name}_{counter}{ext}")
                        counter += 1

                    # 复制文件
                    try:
                        shutil.copy2(src_file, dest_file)
                        self._log(f"✅ 复制成功:{os.path.basename(dest_file)}")
                        file_count += 1
                    except Exception as e:
                        self._log(f"❌ 复制失败:{src_file} 原因:{str(e)}")

            self._log(f"✅ 目录 {target_dir} 处理完成,共复制 {file_count} 个文件")

        self._log(f"\n===== 所有目录处理完成 =====")
        messagebox.showinfo("完成", "文件复制操作已全部执行完毕!")


if __name__ == "__main__":
    # 创建主窗口
    root = tk.Tk()
    # 设置按钮样式(可选)
    style = ttk.Style(root)
    style.configure("Accent.TButton", foreground="white", background="#0078d7")
    # 启动GUI
    app = FileCopyGUI(root)
    root.mainloop()

添加目录

选择结果

开始复制

结果

整体思路

复制代码
使用python中的tkinter 库,创建ui界面
  1. 添加目录按钮
    1. 本质就是在

      复制代码
      self.selected_dirs = []
    2. 这个数组后面添加目录的路径

  2. 清空列表按钮
    1. 本质就是在

      复制代码
      self.selected_dirs = []
    2. 清空这个数组列表

  3. 开始复制按钮
    1. 执行函数

      复制代码
      start_copy()
    2. 这个函数 使用 自身的属性

      1. self.selected_dirs
      2. 进行遍历
      3. 遍历目录以及子目录的文件
      复制代码
      获取源目录的名称
      复制代码
      创建存放结果目标文件夹(不存在则创建)
      1. 将遍历的文件复制到脚本运行目录
  4. 图形界面的 日志ui控件
    1. 这个东西的本质就是
      1. 每次执行的日志信息,在其控件已有的文本内容追加 日志

指定目录的复制

python 复制代码
import os
import shutil
import tkinter as tk
from tkinter import ttk, filedialog, messagebox


class FileCopyGUI:
    def __init__(self, root):
        self.root = root
        self.root.title("文件批量复制工具")
        self.root.geometry("700x550")  # 窗口大小略微调整

        # 存储选中的源目录列表和目标输出目录
        self.selected_dirs = []
        self.output_dir = ""  # 新增:存储用户指定的输出目录

        # 创建UI组件
        self._create_widgets()

    def _create_widgets(self):
        # 1. 目录选择区域(源目录)
        frame_select = ttk.LabelFrame(self.root, text="选择要复制的源目录")
        frame_select.pack(padx=10, pady=10, fill=tk.X)

        # 选择目录按钮
        btn_add_dir = ttk.Button(frame_select, text="添加目录", command=self.add_directory)
        btn_add_dir.pack(side=tk.LEFT, padx=10, pady=5)

        # 清空目录按钮
        btn_clear_dirs = ttk.Button(frame_select, text="清空列表", command=self.clear_directories)
        btn_clear_dirs.pack(side=tk.LEFT, padx=5, pady=5)

        # 目录列表展示
        self.dir_listbox = tk.Listbox(frame_select, height=8, width=80)
        self.dir_listbox.pack(side=tk.LEFT, padx=10, pady=5, fill=tk.X, expand=True)

        # 滚动条
        scrollbar = ttk.Scrollbar(frame_select, orient=tk.VERTICAL, command=self.dir_listbox.yview)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y, pady=5)
        self.dir_listbox.config(yscrollcommand=scrollbar.set)

        # ========== 新增:目标输出目录选择区域 ==========
        frame_output = ttk.LabelFrame(self.root, text="选择文件输出目录")
        frame_output.pack(padx=10, pady=5, fill=tk.X)

        # 显示当前选中的输出目录
        self.output_dir_var = tk.StringVar(value="未选择输出目录")
        lbl_output = ttk.Label(frame_output, textvariable=self.output_dir_var)
        lbl_output.pack(side=tk.LEFT, padx=10, pady=5, fill=tk.X, expand=True)

        # 选择输出目录按钮
        btn_select_output = ttk.Button(frame_output, text="选择目录", command=self.select_output_directory)
        btn_select_output.pack(side=tk.LEFT, padx=10, pady=5)
        # =============================================

        # 2. 操作按钮区域
        frame_operate = ttk.Frame(self.root)
        frame_operate.pack(padx=10, pady=5, fill=tk.X)

        btn_copy = ttk.Button(frame_operate, text="开始复制", command=self.start_copy, style="Accent.TButton")
        btn_copy.pack(side=tk.LEFT, padx=10, pady=5)

        # 3. 日志输出区域
        frame_log = ttk.LabelFrame(self.root, text="复制日志")
        frame_log.pack(padx=10, pady=10, fill=tk.BOTH, expand=True)

        # 日志文本框
        self.log_text = tk.Text(frame_log, height=15, wrap=tk.WORD)
        self.log_text.pack(side=tk.LEFT, padx=10, pady=5, fill=tk.BOTH, expand=True)

        # 日志滚动条
        log_scrollbar = ttk.Scrollbar(frame_log, orient=tk.VERTICAL, command=self.log_text.yview)
        log_scrollbar.pack(side=tk.RIGHT, fill=tk.Y, pady=5)
        self.log_text.config(yscrollcommand=log_scrollbar.set)

        # 设置文本框只读
        self.log_text.config(state=tk.DISABLED)

    def add_directory(self):
        """添加选中的目录到列表"""
        dir_path = filedialog.askdirectory(title="选择要复制的目录")
        if dir_path and dir_path not in self.selected_dirs:
            self.selected_dirs.append(dir_path)
            self.dir_listbox.insert(tk.END, dir_path)
            self._log(f"已添加目录:{dir_path}")

    def clear_directories(self):
        """清空选中的目录列表"""
        self.selected_dirs.clear()
        self.dir_listbox.delete(0, tk.END)
        self._log("已清空目录列表")

    # ========== 新增:选择输出目录的方法 ==========
    def select_output_directory(self):
        """让用户选择文件复制后的输出目录"""
        dir_path = filedialog.askdirectory(title="选择文件输出目录")
        if dir_path:
            self.output_dir = dir_path
            self.output_dir_var.set(f"当前输出目录:{dir_path}")
            self._log(f"已选择输出目录:{dir_path}")

    # =============================================

    def _log(self, message):
        """在日志框中输出信息"""
        self.log_text.config(state=tk.NORMAL)
        self.log_text.insert(tk.END, f"{message}\n")
        self.log_text.see(tk.END)  # 自动滚动到最后一行
        self.log_text.config(state=tk.DISABLED)
        self.root.update_idletasks()  # 实时刷新界面

    def start_copy(self):
        """执行文件复制操作"""
        # 新增:检查输出目录是否选择
        if not self.output_dir:
            messagebox.showwarning("警告", "请先选择文件输出目录!")
            return

        if not self.selected_dirs:
            messagebox.showwarning("警告", "请先添加要复制的目录!")
            return

        self._log(f"===== 开始复制 =====")
        self._log(f"输出根目录:{self.output_dir}")

        # 遍历每个选中的目录
        for target_dir in self.selected_dirs:
            if not os.path.isdir(target_dir):
                self._log(f"⚠️  错误:目录 {target_dir} 不存在,跳过!")
                continue

            # 修改:目标文件夹改为【用户指定的输出目录/源目录名】
            dir_name = os.path.basename(os.path.normpath(target_dir))
            dest_root = os.path.join(self.output_dir, dir_name)  # 核心修改点
            os.makedirs(dest_root, exist_ok=True)
            self._log(f"\n🔄 处理目录:{target_dir} -> {dest_root}(文件平铺)")

            # 遍历所有文件并复制
            file_count = 0
            for root, dirs, files in os.walk(target_dir):
                for file in files:
                    src_file = os.path.join(root, file)
                    dest_file = os.path.join(dest_root, file)

                    # 处理重名文件
                    counter = 1
                    while os.path.exists(dest_file):
                        file_name, ext = os.path.splitext(file)
                        dest_file = os.path.join(dest_root, f"{file_name}_{counter}{ext}")
                        counter += 1

                    # 复制文件
                    try:
                        shutil.copy2(src_file, dest_file)
                        self._log(f"✅ 复制成功:{os.path.basename(dest_file)}")
                        file_count += 1
                    except Exception as e:
                        self._log(f"❌ 复制失败:{src_file} 原因:{str(e)}")

            self._log(f"✅ 目录 {target_dir} 处理完成,共复制 {file_count} 个文件")

        self._log(f"\n===== 所有目录处理完成 =====")
        messagebox.showinfo("完成", "文件复制操作已全部执行完毕!")


if __name__ == "__main__":
    # 创建主窗口
    root = tk.Tk()
    # 设置按钮样式(可选)
    style = ttk.Style(root)
    style.configure("Accent.TButton", foreground="white", background="#0078d7")
    # 启动GUI
    app = FileCopyGUI(root)
    root.mainloop()

小工具下载地址

https://www.123865.com/s/lWZKVv-Zt6av?pwd=gyy0#

提取码:gyy0

压缩密码:xiji

相关推荐
副露のmagic2 小时前
更弱智的算法学习day 38
python·学习
nvd112 小时前
Python 连接 MCP Server 全指南
开发语言·python
电商API&Tina2 小时前
合规电商数据采集 API|多平台实时数据抓取,告别爬虫封号风险
大数据·开发语言·前端·数据库·爬虫·python
天才测试猿2 小时前
自动化测试用例编写
自动化测试·软件测试·python·测试工具·程序人生·职场和发展·测试用例
忘忧记2 小时前
基于Tkinter基础模板的开发流程指南
开发语言·python
姚瑞南2 小时前
【AI 风向标】强化学习(RL):智能体自我优化的学习范式
人工智能·经验分享·python·gpt·深度学习·学习·机器学习
Zomcxj2 小时前
PasteLabel 图像编辑器:贴图标注,解决样本采集难题
人工智能·python·编辑器·贴图
未定义.2212 小时前
第4篇:企业级框架搭建,Pytest+PO模式从0到1实战
python·ui·自动化·jenkins·集成测试·pytest
轻竹办公PPT2 小时前
AI 生成 PPT 真能替代人工吗?多款工具深度测试
人工智能·python·powerpoint