递归地将文件复制到子目录中

3

我需要将所有文件和文件夹复制到当前文件夹的子目录中。最好的方法是什么?我尝试了下面的代码片段,但如果目标目录已经存在,则会失败。

def copy(d=os.path.curdir):
    dest = "t"
    for i in os.listdir(d):
        if os.path.isdir(i):
            shutil.copytree(i, dest)
        else:
            shutil.copy(i, dest)

我有一种感觉,同样的任务可以用更好、更简单的方式完成。我该怎么做呢?


当您开始复制时,目标子文件夹是否为空? - Sven Marnach
代码片段完全有 bug。1)为什么要在子目录上使用 copytree 而不是在根目录上使用?2)ddest 没有被使用。 - khachik
@khachik 抱歉,我匆忙打字。[2] 已经处理好了。 - user277465
@khachik [1] 我感觉将 directory/ 的内容复制到 directory/inner_directory 中会导致问题,因为 inner_directory 会尝试复制自身。我猜可能会出现 OSError 错误。 - user277465
@Sven 是的,最初我要复制到的子文件夹将是空的。 - user277465
在这种情况下,可以使用shutil.copytree(os.path.join(i), os.path.join(dest, i)。请参考我的回答。 - khachik
5个回答

2

我不会用Python来做这件事,但是我想到了以下解决方案。看起来并不简单,但应该可以工作,并且可以简化(没有检查,抱歉,现在无法访问电脑):

def copyDirectoryTree(directory, destination, preserveSymlinks=True):
  for entry in os.listdir(directory):
    entryPath = os.path.join(directory, entry)
    if os.path.isdir(entryPath):
      entrydest = os.path.join(destination, entry)
      if os.path.exists(entrydest):
        if not os.path.isdir(entrydest):
          raise IOError("Failed to copy thee, the destination for the `" + entryPath + "' directory exists and is not a directory")
        copyDirectoryTree(entrypath, entrydest, preserveSymlinks)
      else:
        shutil.copytree(entrypath, entrydest, preserveSymlinks)
    else: #symlinks and files
      if preserveSymlinks:
        shutil.copy(entryPath, directory)
      else:
        shutil.copy(os.path.realpath(entryPath), directory)

1

嗯,我本来希望避免这种情况的,但看来没有其他办法了。谢谢! - user277465

1

为了扩展mamnun的答案,

如果你想要直接调用操作系统,我建议使用cp -r,因为你似乎想要递归复制目录。


0

这是我编写的 Python 递归复制方法,看起来很有效 :)

def copy_all(fr, to, overwrite=True):
  fr = os.path.normpath(fr)
  to = os.path.normpath(to)

  if os.path.isdir(fr):
    if (not os.path.exists(to + os.path.basename(fr)) and not
    os.path.basename(fr) == os.path.basename(to)):
      to += "/" + os.path.basename(fr)
      mkdirs(to)
    for file in os.listdir(fr):
      copy_all(fr + "/" + file, to + "/")
  else: #symlink or file
    dest = to
    if os.path.isdir(to):
      dest += "/"
      dest += os.path.basename(fr)

    if overwrite and (os.path.exists(dest) or os.path.islink(dest)
      rm(dest)

    if os.path.isfile(fr):
      shutil.copy2(fr, dest)
    else: #has to be a symlink
      os.symlink(os.readlink(fr), dest)  


def mkdirs(path):                                                 
  if not os.path.isdir(path):
    os.makedirs(path)


def rm(path):                                                     
  if os.path.isfile(path) or os.path.islink(path):
    os.remove(path)
  elif os.path.isdir(path):
    for file in os.listdir(path):
      fullpath = path+"/"+file
      os.rmdir(fullpath)

0

你真的需要使用Python吗?因为shutil函数无法复制所有文件元数据和组权限。为什么不尝试使用内置的操作系统命令,如Linux中的cp和Windows中的xcopy呢?

你甚至可以尝试从Python中运行这些命令。

import os

os.system("cp file1 file2")

希望这能帮到你。


嗯,使用os.system是一个好的实践吗?假设我会采用这种方式,我需要某种类型的bash管道;这将使代码依赖于平台。 - user277465
@khachik:对于Windows系统,可以使用xcopy命令。@zubin71:还有另一种解决方案。我认为,cpxcopy在复制文件和目录方面能做得更好。 - Max

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接