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

时间:2022-11-24 10:34:14

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. What I want to do is move the contents of 'src Directory' to 'Dst Directory' and overwrite anyfiles that exist with the same name. So for example 'Src Directory\file.txt' needs to be moved to 'Dst Directory\' and overwrite the existing file.txt. The same applies for some folders, moving a folder and merging the contents with the same folder in 'dst directory'

我有一个目录“Dst目录”,里面有文件和文件夹,还有“src目录”,里面也有文件和文件夹。我要做的是将“src目录”的内容移动到“Dst目录”并覆盖存在同名的任何文件。例如,Src目录\文件。txt'需要移动到'Dst目录\'并覆盖现有文件.txt。同样的情况也适用于一些文件夹,移动一个文件夹并将内容与“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; it'll just put the folder inside the existing folder.

我目前使用shutil。将src的内容移动到dst,但是如果文件已经存在,并且它不会合并文件夹,它就不会这样做。它将把文件夹放在现有的文件夹中。

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. This will be repeated for adding new files or new versions of files etc which is why it needs to overwrite and merge

更新:使事情更清晰;我所做的是将归档解压缩到Dst目录,然后在那里移动Src目录的内容并重新压缩,有效地更新zip归档中的文件。这将重复用于添加新文件或文件的新版本等等,这就是为什么它需要覆盖和合并

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. Hope that helps some people!

我用distutil .dir_util解决了我的问题。copy_tree(src, dst)将文件夹和文件从src目录复制到dst目录,并在必要的地方覆盖/合并。希望这对一些人有所帮助!

Hope that makes sense, thanks!

希望你能理解,谢谢!

6 个解决方案

#1


37  

Use copy() instead, which is willing to overwrite destination files. If you then want the first tree to go away, just rmtree() it separately once you are done iterating over it.

使用copy()代替,它愿意覆盖目标文件。如果您希望第一棵树消失,那么在遍历它之后,只需分别使用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. For each directory, check if it exists on the destination side, and os.makedirs() it if it is missing. For each file, simply shutil.copy() and the file will be created or overwritten, whichever is appropriate.

执行操作os.walk()遍历源树。对于每个目录,检查它是否存在于目标端,如果它丢失,则检查os.makedirs()。对于每个文件,只需创建shutil.copy()并将创建或覆盖该文件,以适当的方式。

#2


46  

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):
            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. Any files or directories that already exist in the destination but not in the source will remain untouched.

任何预先存在的文件将首先被删除(通过os.remove),然后被相应的源文件替换。在目的地中已经存在的任何文件或目录,但源代码中不存在的文件或目录将保持不变。

#3


6  

Since none of the above worked for me, so I wrote my own recursive function. Call Function copyTree(dir1, dir2) to merge directories. Run on multi-platforms Linux and Windows.

由于上述方法对我都不起作用,所以我编写了自己的递归函数。调用函数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)

#4


3  

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)

#5


1  

Have a look at: os.remove to remove existing files.

看看:os。删除已存在的文件。

#6


0  

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)

#1


37  

Use copy() instead, which is willing to overwrite destination files. If you then want the first tree to go away, just rmtree() it separately once you are done iterating over it.

使用copy()代替,它愿意覆盖目标文件。如果您希望第一棵树消失,那么在遍历它之后,只需分别使用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. For each directory, check if it exists on the destination side, and os.makedirs() it if it is missing. For each file, simply shutil.copy() and the file will be created or overwritten, whichever is appropriate.

执行操作os.walk()遍历源树。对于每个目录,检查它是否存在于目标端,如果它丢失,则检查os.makedirs()。对于每个文件,只需创建shutil.copy()并将创建或覆盖该文件,以适当的方式。

#2


46  

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):
            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. Any files or directories that already exist in the destination but not in the source will remain untouched.

任何预先存在的文件将首先被删除(通过os.remove),然后被相应的源文件替换。在目的地中已经存在的任何文件或目录,但源代码中不存在的文件或目录将保持不变。

#3


6  

Since none of the above worked for me, so I wrote my own recursive function. Call Function copyTree(dir1, dir2) to merge directories. Run on multi-platforms Linux and Windows.

由于上述方法对我都不起作用,所以我编写了自己的递归函数。调用函数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)

#4


3  

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)

#5


1  

Have a look at: os.remove to remove existing files.

看看:os。删除已存在的文件。

#6


0  

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)