Python-перемещение и перезапись файлов и папок

У меня есть каталог "DST Directory", в котором есть файлы и папки, и у меня есть "src Directory", в котором также есть файлы и папки. То, что я хочу сделать, это переместить содержимое "каталога src" в "каталог Dst" и перезаписать любые файлы, которые существуют с тем же именем. Так, например, ' Src Directoryfile.txt "необходимо переместить в" DST Directory " и перезаписать существующий файл.формат txt. То же самое относится к некоторым папкам, перемещая папку и объединяя содержимое с той же папкой в папка 'ДСТ'

в настоящее время я использую shutil.переместить, чтобы переместить содержимое src в dst, но это не будет делать, если файлы уже существуют, и он не будет объединять папки; он просто поместит папку внутри существующей папки.

Update: чтобы сделать вещи немного яснее; то, что я делаю, это распаковка архива В КАТАЛОГ Dst, а затем перемещение содержимого каталога Src туда и резипинг, эффективное обновление файлов в zip-архиве. Это будет повторено для добавления новых файлов или новых версий файлов и т. д. Поэтому он должен перезаписать и слияния

решено: я решил свою проблему с помощью distutils.dir_util.copy_tree (src, dst), это копирует папки и файлы из каталога src в каталог dst и перезаписывает/объединяет, где необходимо. Надеюсь, это поможет некоторым людям!

надеюсь, что это имеет смысл, спасибо!

6 ответов


использовать 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() и файл будет создан или перезаписан, в зависимости от ситуации.


это будет проходить через исходный каталог, создавать любые каталоги, которые еще не существуют в целевом каталоге, и перемещать файлы из исходного каталога в целевой каталог:

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)

все ранее существовавшие файлы будут удалены первыми (через os.remove) перед заменой на соответствующий исходный файл. Любые файлы или каталоги, которые уже существуют в месте назначения, но не в источнике останутся нетронутыми.


поскольку ни один из вышеперечисленных не работал для меня, поэтому я написал свою собственную рекурсивную функцию. Вызов функция 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)

Если Вам также нужно перезаписать файлы с флагом только для чтения, используйте это:

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)

посмотреть: os.remove для удаления существующих файлов.


у меня была похожая проблема. Я хотел переместить файлы и структуры папок и перезаписать существующие файлы, но не удалять ничего, что находится в структуре папок назначения.

Я решил это с помощью os.walk(), рекурсивно вызывая мою функцию и используя shutil.move() на файлы, которые я хотел перезаписать и папки, которые не существовали.

Он работает 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)