使用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

相关推荐
lupai15 小时前
手机在网状态接口实测效果与质量评估
大数据·python·智能手机·api接口
荷蒲16 小时前
【小白量化Qbuddy】用AI设计miniQMT指标公式计算量化平台
人工智能·python·机器人
阿童木写作16 小时前
跨境电商图片翻译工具,批量翻译视频字幕一键抠图
人工智能·python·音视频
何以解忧,唯有..17 小时前
Pydantic 介绍与使用:Python 数据校验的现代方案
数据库·python·microsoft
又幸福了哥18 小时前
Python入门到高级(知识点七)
python
又幸福了哥19 小时前
Python入门到高级(知识点六)
python
维克兜率天19 小时前
【维克】动量指标家族:RSI、ROC、CCI、Momentum全面解析
python·算法
XZ-07000120 小时前
week2-1-可视化
开发语言·python
Java后端的Ai之路20 小时前
14、Python - 责任链模式
服务器·开发语言·人工智能·python·责任链模式
张人玉20 小时前
基于 Python 机器学习 与 PyQt5 桌面框架开发的可视化分析系统——基于大数据的网上购物消费行为分析可视化大屏
python·qt·机器学习·echarts·three.js