在Python中递归复制文件或目录

paf*_*fcu 112 python

Python似乎具有复制文件(例如shutil.copy)和复制目录的函数(例如)的功能,shutil.copytree但我没有找到任何处理这两者的函数.当然,检查是否要复制文件或目录是微不足道的,但这似乎是一个奇怪的遗漏.

真的没有像unix cp -r命令那样工作的标准函数,即递归支持目录和文件以及副本吗?在Python中解决这个问题最优雅的方法是什么?

tzo*_*zot 136

我建议你先调用shutil.copytree,如果抛出异常,则重试shutil.copy.

import shutil, errno

def copyanything(src, dst):
    try:
        shutil.copytree(src, dst)
    except OSError as exc: # python >2.5
        if exc.errno == errno.ENOTDIR:
            shutil.copy(src, dst)
        else: raise
Run Code Online (Sandbox Code Playgroud)

  • 1)因为在Python世界中EAFP(比请求更容易请求宽恕)优于LBYL(在你跳跃之前看).如果听起来很新,我可以为您提供相关链接.2)库函数已经间接检查了,所以为什么要复制支票?3)没有什么能阻止`shutil.copytree`功能在未来改进和管理这两种情况.4)Python中的异常并不是那么特殊; 例如,通过抛出StopIteration异常来停止迭代. (30认同)
  • 我认为简单地检查src是否是使用os.path.isdir(src)的目录而不是像这样捕获异常会更清晰.或者是否有一些特殊原因应该在这里使用例外? (16认同)
  • 实际上,在这种情况下,异常确实有一个明显的客观优势:完全可能(尽管极不可能)类型在检查和调用正确函数之间发生变化. (5认同)
  • 好吧,在这种情况下,处理异常需要6行,而检查类型需要4行.不多,但它最终加起来.另外,正如你所说,copytree有一天也可以很好地支持文件.但是不可能分辨出这种实现是什么样的.也许它会在复制工作的某些情况下引发异常?在这种情况下,我的代码会因为增加的功能而突然停止工作.但是你可能是正确的,异常在Python中非常普遍,我发现这很烦人,但可能是因为我似乎从未习惯它 (2认同)
  • 在我个人看来,添加核心功能除了不好的做法,无论你使用哪种语言都无关紧要.它将功能放在一个很多开发人员都不会搜索的地方.此外,如果你不写评论,一个经验不足的python开发人员不会真正理解这次重试的目的是什么.如果你需要为这样一个微不足道的事情添加评论,你的代码风格上的东西是错误的.最后,编写if/else将导致更容易阅读的代码. (2认同)

mon*_*eki 12

要在增加Tzot的GNS答案,这里的递归复制文件和文件夹的另一种方式。(Python 3.X)

import os, shutil

root_src_dir = r'C:\MyMusic'    #Path/Location of the source directory
root_dst_dir = 'D:MusicBackUp'  #Path to the destination folder

for src_dir, dirs, files in os.walk(root_src_dir):
    dst_dir = src_dir.replace(root_src_dir, root_dst_dir, 1)
    if not os.path.exists(dst_dir):
        os.makedirs(dst_dir)
    for file_ in files:
        src_file = os.path.join(src_dir, file_)
        dst_file = os.path.join(dst_dir, file_)
        if os.path.exists(dst_file):
            os.remove(dst_file)
        shutil.copy(src_file, dst_dir)
Run Code Online (Sandbox Code Playgroud)

如果这是您第一次并且不知道如何递归复制文件和文件夹,我希望这会有所帮助。


小智 5

shutil.copy并且shutil.copy2正在复制文件。

shutil.copytree复制一个包含所有文件和所有子文件夹的文件夹。shutil.copytree正在使用shutil.copy2复制文件。

所以cp -r你所说的类比是shutil.copytree因为cp -r目标和复制文件夹及其文件/子文件夹,如shutil.copytree. 没有-r cpshutil.copyshutil.copy2做的副本文件。