在Python中递归复制文件或目录
Python似乎有复制文件的函数(例如在Python中递归复制文件或目录,python,Python,Python似乎有复制文件的函数(例如shutil.copy)和复制目录的函数(例如shutil.copytree),但我还没有找到任何同时处理这两个问题的函数。当然,检查是否要复制文件或目录很简单,但这似乎是一个奇怪的遗漏 是否真的没有像unixcp-r命令那样工作的标准函数,即支持目录和文件以及递归复制?在Python中解决这个问题最优雅的方法是什么?Unixcp不“同时支持目录和文件”: betelgeuse:tmp james$ cp source/ dest/ cp: source/
shutil.copy
)和复制目录的函数(例如shutil.copytree
),但我还没有找到任何同时处理这两个问题的函数。当然,检查是否要复制文件或目录很简单,但这似乎是一个奇怪的遗漏
是否真的没有像unix
cp-r
命令那样工作的标准函数,即支持目录和文件以及递归复制?在Python中解决这个问题最优雅的方法是什么?Unixcp
不“同时支持目录和文件”:
betelgeuse:tmp james$ cp source/ dest/
cp: source/ is a directory (not copied).
要使cp复制一个目录,您必须使用“-r”标志手动告诉cp它是一个目录
当传递一个文件名时-cp-r
会有一些中断,因为源代码很乐意只复制一个文件;copytree不会。我建议您首先调用,如果引发异常,请使用重试
python shutil.copytree方法一团糟。我已经做了一个正确的工作:
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.copy
和shutil.copy2
正在复制文件
shutil.copytree
复制包含所有文件和所有子文件夹的文件夹shutil.copytree
正在使用shutil.copy2
复制文件
因此,与您所说的cp-r
类似的是shutil.copytree
,因为cp-r
以文件夹及其文件/子文件夹为目标并进行复制,如shutil.copytree
。如果不使用-r
cp
复制文件,如shutil.copy
和shutil.copy2
do。要添加和回答,这里有一种递归复制文件和文件夹的替代方法。(Python 3.X)
如果这是你第一次,但你不知道如何递归复制文件和文件夹,我希望这会有所帮助。包括copytree()的代码,该代码演示如何处理普通文件、符号链接和目录。这个答案没有解决这个问题。这应该是评论,而不是回答。是的,这是一团糟。Python试图反映底层系统调用,从而使可视界面变得更糟糕。虽然在复制文件和复制树之间切换并不困难,但这并不是必须的。也许可以在Python bug跟踪器上提交一个增强请求,以允许
copytree
复制单个文件?我认为复制树就是您想要的。我认为使用os.path.isdir(src)简单地检查src是否是一个目录,而不是捕获这样的异常会更干净。或者有什么特别的原因应该在这里使用异常吗?1)因为在Python世界中,EAFP(请求原谅比允许更容易)比LBYL(三思而后行)更受欢迎。我可以为您提供有关这方面的链接,如果这对您来说是新的。2) 库函数已经间接地检查了这一点,那么为什么要复制检查呢?3) 没有任何东西可以阻止shutil.copytree
函数在将来改进和管理这两种情况。4) 在Python中,异常并不是那么例外;e、 迭代通过抛出StopIteration异常来停止。在这种情况下,处理异常需要6行,而检查类型需要4行。虽然不多,但最终还是加起来了。另外,正如您所说,copytree将来也可能很好地支持文件。但不可能知道该实现会是什么样子。也许它会在复制有效的情况下抛出异常?在这种情况下,我的代码会因为添加的功能而突然停止工作。但你可能是对的,异常在Python中非常常见,我觉得这很烦人,但这可能是因为我似乎从未习惯于它。实际上,在这种情况下,异常有一个明显的客观优势:它是完全可能的(尽管可能性很小)在我个人看来,在except中添加核心功能是一种不好的做法,不管您使用哪种语言。它将功能放在了一个很多开发人员都不会搜索的地方。此外,如果您不编写注释,经验较少的python开发人员将无法真正理解此重试的目的。如果您需要为像这里这样的小事添加注释,那么您的代码样式中的某些内容是错误的。最后,编写if/else会使代码更易于阅读。该代码适用于单个文件检查(检查覆盖问题),但不适用于二进制文件,如“zip”。为什么不使用简单的python文件拷贝而不是逐行读/写呢?我认为您不理解这个问题。尝试shutil.copytree('C:\myfile.txt','C:\otherfile')
。它不起作用。这就是OP要问的。。。7年前,当然不行了。就像cp不处理文件夹一样。你需要一个特别的选择。copy和copytree是处理复制的最佳方式。如果copytree可以将目标和文件放在一起,那么很容易出错。您必须知道Linux和Python的目标是什么。那很难。另外还有人在这里发表了评论,但看到问题和回复,忍不住要回答。优雅的方法是知道你想要做什么,而不是没有任何控制的通用副本。
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('..')
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)