Python - 移动并覆盖文件和文件夹

93 投票
7 回答
288678 浏览
提问于 2025-04-17 02:18

我有一个文件夹,叫做“目标目录”,里面有一些文件和文件夹。还有一个叫“源目录”的文件夹,里面也有文件和文件夹。我想做的是把“源目录”里的内容移动到“目标目录”,并且如果有同名的文件,就把它们覆盖掉。比如说,“源目录”里的file.txt需要移动到“目标目录”,并覆盖掉那里的file.txt。对于一些文件夹也是一样,移动一个文件夹并把它的内容和“目标目录”里同名的文件夹合并。

我现在使用的是shutil.move来把“源目录”的内容移动到“目标目录”,但是如果文件已经存在,它就不执行移动,也不会合并文件夹;它只会把文件夹放在已有文件夹里面。

更新一下:为了让事情更清楚,我的操作是先把一个压缩包解压到“目标目录”,然后再把“源目录”的内容移动过去,最后再压缩,这样就能更新压缩包里的文件。这种操作会重复进行,以便添加新文件或新版本的文件,所以需要覆盖和合并。

7 个回答

10

因为上面提到的方法都不适合我,所以我自己写了一个递归函数。你可以调用这个函数 copyTree(dir1, dir2) 来合并两个文件夹。这个函数可以在Linux和Windows这两个平台上运行。

def forceMergeFlatDir(srcDir, dstDir):
    if not os.path.exists(dstDir):
        os.makedirs(dstDir)
    for item in os.listdir(srcDir):
        srcFile = os.path.join(srcDir, item)
        dstFile = os.path.join(dstDir, item)
        forceCopyFile(srcFile, dstFile)

def forceCopyFile (sfile, dfile):
    if os.path.isfile(sfile):
        shutil.copy2(sfile, dfile)

def isAFlatDir(sDir):
    for item in os.listdir(sDir):
        sItem = os.path.join(sDir, item)
        if os.path.isdir(sItem):
            return False
    return True


def copyTree(src, dst):
    for item in os.listdir(src):
        s = os.path.join(src, item)
        d = os.path.join(dst, item)
        if os.path.isfile(s):
            if not os.path.exists(dst):
                os.makedirs(dst)
            forceCopyFile(s,d)
        if os.path.isdir(s):
            isRecursive = not isAFlatDir(s)
            if isRecursive:
                copyTree(s, d)
            else:
                forceMergeFlatDir(s, d)
74

这个代码会遍历源文件夹,创建目标文件夹中还不存在的文件夹,然后把文件从源文件夹移动到目标文件夹:

import os
import shutil

root_src_dir = 'Src Directory\\'
root_dst_dir = 'Dst Directory\\'

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):
            # in case of the src and dst are the same file
            if os.path.samefile(src_file, dst_file):
                continue
            os.remove(dst_file)
        shutil.move(src_file, dst_dir)

在替换之前,任何已经存在的文件会先被删除(通过 os.remove),然后再用源文件夹中的对应文件替换掉。目标文件夹中已经存在但源文件夹没有的文件或文件夹将不会受到影响,保持不变。

67

可以使用 copy() 函数,它会覆盖目标文件。如果你想要删除第一个文件夹,等你处理完后,可以单独用 rmtree() 来删除它。

http://docs.python.org/library/shutil.html#shutil.copy

http://docs.python.org/library/shutil.html#shutil.rmtree

更新:

可以对源文件夹使用 os.walk()。对于每个文件夹,检查它在目标位置是否存在,如果不存在,就用 os.makedirs() 创建它。对于每个文件,直接用 shutil.copy(),这样文件就会被创建或覆盖,具体取决于情况。

撰写回答