简体   繁体   English

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

[英]Python - Move and overwrite files and folders

I have a directory, 'Dst Directory', which has files and folders in it and I have 'src Directory' which also has files and folders in it.我有一个目录“Dst Directory”,里面有文件和文件夹,我有一个“src Directory”,里面也有文件和文件夹。 What I want to do is move the contents of 'src Directory' to 'Dst Directory' and overwrite anyfiles that exist with the same name.我想要做的是将 'src Directory' 的内容移动到 'Dst Directory' 并覆盖任何同名存在的文件。 So for example 'Src Directory\\file.txt' needs to be moved to 'Dst Directory\\' and overwrite the existing file.txt.因此,例如“Src Directory\\file.txt”需要移动到“Dst Directory\\”并覆盖现有的file.txt。 The same applies for some folders, moving a folder and merging the contents with the same folder in 'dst directory'这同样适用于某些文件夹,移动文件夹并将内容与“dst 目录”中的同一文件夹合并

I'm currently using shutil.move to move the contents of src to dst but it won't do it if the files already exist and it won't merge folders;我目前正在使用 shutil.move 将 src 的内容移动到 dst 但如果文件已经存在,它就不会这样做并且不会合并文件夹; it'll just put the folder inside the existing folder.它只会将文件夹放在现有文件夹中。

Update: To make things a bit clearer, what I'm doing is unzipping an archive to the Dst Directory and then moving the contents of Src Directory there and rezipping, effectively updating files in the zip archive.更新:为了让事情更清楚一点,我正在做的是将存档解压缩到 Dst 目录,然后将 Src 目录的内容移到那里并重新压缩,有效地更新 zip 存档中的文件。 This will be repeated for adding new files or new versions of files etc which is why it needs to overwrite and merge这将重复添加新文件或新版本的文件等,这就是为什么它需要覆盖和合并

Solved: I solved my problem by using distutils.dir_util.copy_tree(src, dst), this copies the folders and files from src directory to dst directory and overwrites/merges where neccesary.已解决:我通过使用 distutils.dir_util.copy_tree(src, dst) 解决了我的问题,这会将文件夹和文件从 src 目录复制到 dst 目录,并在需要时覆盖/合并。 Hope that helps some people!希望能帮助到一些人!

Hope that makes sense, thanks!希望有道理,谢谢!

This will go through the source directory, create any directories that do not already exist in destination directory, and move files from source to the destination directory:这将遍历源目录,创建目标目录中尚不存在的任何目录,并将文件从源目录移动到目标目录:

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)

Any pre-existing files will be removed first (via os.remove ) before being replace by the corresponding source file.在被相应的源文件替换之前,任何预先存在的文件将首先被删除(通过os.remove )。 Any files or directories that already exist in the destination but not in the source will remain untouched.目标中已存在但源中不存在的任何文件或目录将保持不变。

Use copy() instead, which is willing to overwrite destination files.改用copy() ,它愿意覆盖目标文件。 If you then want the first tree to go away, just rmtree() it separately once you are done iterating over it.如果您希望第一棵树消失,只需在完成迭代后单独使用rmtree()即可。

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

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

Update:更新:

Do an os.walk() over the source tree.在源树上执行os.walk() For each directory, check if it exists on the destination side, and os.makedirs() it if it is missing.对于每个目录,检查它是否存在于目标端,如果缺少,则检查os.makedirs() For each file, simply shutil.copy() and the file will be created or overwritten, whichever is appropriate.对于每个文件,只需shutil.copy() ,文件将被创建或覆盖,以适当的为准。

Since none of the above worked for me, so I wrote my own recursive function.由于以上都不适合我,所以我编写了自己的递归函数。 Call Function copyTree(dir1, dir2) to merge directories.调用函数 copyTree(dir1, dir2) 合并目录。 Run on multi-platforms Linux and Windows.在多平台 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)

If you also need to overwrite files with read only flag use this:如果您还需要使用只读标志覆盖文件,请使用以下命令:

def copyDirTree(root_src_dir,root_dst_dir):
"""
Copy directory tree. Overwrites also read only files.
:param root_src_dir: source directory
:param root_dst_dir:  destination 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):
            try:
                os.remove(dst_file)
            except PermissionError as exc:
                os.chmod(dst_file, stat.S_IWUSR)
                os.remove(dst_file)

        shutil.copy(src_file, dst_dir)

I had a similar problem.我有一个类似的问题。 I wanted to move files and folder structures and overwrite existing files, but not delete anything which is in the destination folder structure.我想移动文件和文件夹结构并覆盖现有文件,但不删除目标文件夹结构中的任何内容。

I solved it by using os.walk() , recursively calling my function and using shutil.move() on files which I wanted to overwrite and folders which did not exist.我通过使用os.walk() ,递归调用我的函数并在我想覆盖的文件和不存在的文件夹上使用shutil.move()解决了它。

It works like shutil.move() , but with the benefit that existing files are only overwritten, but not deleted.它的工作原理类似于shutil.move() ,但好处是现有文件只会被覆盖,而不会被删除。

import os
import shutil

def moverecursively(source_folder, destination_folder):
    basename = os.path.basename(source_folder)
    dest_dir = os.path.join(destination_folder, basename)
    if not os.path.exists(dest_dir):
        shutil.move(source_folder, destination_folder)
    else:
        dst_path = os.path.join(destination_folder, basename)
        for root, dirs, files in os.walk(source_folder):
            for item in files:
                src_path = os.path.join(root, item)
                if os.path.exists(dst_file):
                    os.remove(dst_file)
                shutil.move(src_path, dst_path)
            for item in dirs:
                src_path = os.path.join(root, item)
                moverecursively(src_path, dst_path)

You can use this to copy directory overwriting existing files:您可以使用它来复制目录覆盖现有文件:

import shutil
shutil.copytree("src", "dst", dirs_exist_ok=True)

dirs_exist_ok argument was added in Python 3.8. dirs_exist_ok参数是在 Python 3.8 中添加的。

See docs: https://docs.python.org/3/library/shutil.html#shutil.copytree请参阅文档: https : //docs.python.org/3/library/shutil.html#shutil.copytree

看看: os.remove删除现有文件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM