Python脚本能否完整复制含子文件夹的目录并实现复制监控?
问题解答
1. 原脚本是否能复制包含子文件夹的完整目录?
原脚本的shutil.copytree本身支持递归复制所有子文件夹及文件,但存在两个冗余/问题点:
- 代码中
files = os.listdir(src_dir)这一行完全无用,copytree会自行遍历源目录的所有层级内容 - 若目标目录
dest_dir已存在,copytree会直接抛出FileExistsError导致复制中断(Python 3.8+可通过dirs_exist_ok=True参数解决)
2. 如何实现复制文件的实时监控?
原脚本的日志函数仅打印当前处理的目录,无法监控单个文件的复制状态。可以通过以下两种方式实现文件级监控:
方式一:自定义复制函数配合shutil.copytree
修改脚本,添加自定义复制函数记录每个文件的复制操作,同时完善日志配置:
import shutil import os import logging # 配置日志:输出到控制台,显示时间、级别和内容 logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s', handlers=[logging.StreamHandler()] ) def copy_with_log(src_file, dest_file): """带日志的文件复制函数,保留文件元数据""" logging.info(f"正在复制: {src_file} -> {dest_file}") try: shutil.copy2(src_file, dest_file) except Exception as e: logging.error(f"复制失败 [{src_file}]: {str(e)}") def log_current_dir(path, names): """记录当前处理的目录""" logging.info(f"处理目录: {path}") return [] # 不忽略任何文件或子目录 src_dir = r'\\networkDrive1\allFolders' dest_dir = r'\\networkDrive2\folder1\folder2\destinationFolder' # 处理目标目录已存在的情况(Python 3.8+支持dirs_exist_ok) if os.path.exists(dest_dir): logging.warning(f"目标目录 {dest_dir} 已存在,将跳过已存在的目录结构") shutil.copytree( src_dir, dest_dir, ignore=log_current_dir, copy_function=copy_with_log, dirs_exist_ok=True # 允许目标目录存在,避免报错 )
方式二:用os.walk手动遍历复制(更灵活)
通过os.walk遍历源目录的所有层级,逐个复制文件,适合需要更精细控制的场景:
import shutil import os import logging logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s', handlers=[logging.StreamHandler()] ) src_dir = r'\\networkDrive1\allFolders' dest_dir = r'\\networkDrive2\folder1\folder2\destinationFolder' for root, dirs, files in os.walk(src_dir): # 构建当前目录在目标路径中的对应位置 target_root = root.replace(src_dir, dest_dir, 1) # 创建目标目录(不存在则创建,已存在则跳过) os.makedirs(target_root, exist_ok=True) logging.info(f"进入目录: {root}") for file in files: src_path = os.path.join(root, file) target_path = os.path.join(target_root, file) # 可选:跳过已存在的文件 if os.path.exists(target_path): logging.debug(f"文件已存在,跳过: {target_path}") continue logging.info(f"正在复制: {src_path} -> {target_path}") try: shutil.copy2(src_path, target_path) except Exception as e: logging.error(f"复制失败 [{src_path}]: {str(e)}")
额外注意事项
- 针对1TB的大体积网络复制,建议添加重试机制(比如复制失败时重试2-3次),避免因网络波动中断任务
shutil.copy2会保留文件的元数据(修改时间、权限等),若无需保留可改用shutil.copy- 若需要持久化日志,可在
logging.basicConfig中添加logging.FileHandler('copy_task.log'),将日志同时写入文件
内容的提问来源于stack exchange,提问作者Andrew Feenan
相关产品推荐
相关产品推荐

