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

Python 似乎有用于复制文件的函数(例如 shutil.copy)和用于复制目录的函数(例如 shutil.copytree) ,但我还没有找到任何同时处理这两种函数的函数。当然,检查是否要复制文件或目录很简单,但这似乎是一个奇怪的遗漏。

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

202989 次浏览

Unix cp不“同时支持目录和文件”:

betelgeuse:tmp james$ cp source/ dest/
cp: source/ is a directory (not copied).

要使 cp 复制目录,必须使用’-r’标志手动告诉 cp 它是一个目录。

但是这里有一些断开的地方-当传递一个文件名时,cp -r代码会很高兴地只复制一个文件,而复制树则不会。

我建议您首先调用 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 in (errno.ENOTDIR, errno.EINVAL):
shutil.copy(src, dst)
else: raise

Python shutil.coptree 方法一团糟,我已经做了一个正确的方法:

def copydirectorykut(src, dst):
os.chdir(dst)
list=os.listdir(src)
nom= src+'.txt'
fitx= open(nom, 'w')


for item in list:
fitx.write("%s\n" % item)
fitx.close()


f = open(nom,'r')
for line in f.readlines():
if "." in line:
shutil.copy(src+'/'+line[:-1],dst+'/'+line[:-1])
else:
if not os.path.exists(dst+'/'+line[:-1]):
os.makedirs(dst+'/'+line[:-1])
copydirectorykut(src+'/'+line[:-1],dst+'/'+line[:-1])
copydirectorykut(src+'/'+line[:-1],dst+'/'+line[:-1])
f.close()
os.remove(nom)
os.chdir('..')

shutil.copyshutil.copy2正在复制文件。

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

所以你说的类似于 cp -r的是 shutil.copytree,因为 cp -r的目标是并复制一个文件夹及其文件/子文件夹,如 shutil.copytree。没有 -rcp复制像 shutil.copyshutil.copy2这样的文件。

要添加 扎特氏症答案,这里有一种递归复制文件和文件夹的替代方法

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)

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

迄今为止,我发现的最快、最优雅的方法是使用 Dir _ util原生包的 Copy _ tree函数:

import distutils.dir_util
from_dir = "foo/bar"
to_dir = "truc/machin"
distutils.dir_util.copy_tree(from_dir, to_dir)