Python-déplacer et écraser des fichiers et des dossiers

J'ai un répertoire, 'DST Directory' , qui contient des fichiers et des dossiers et j'ai 'src Directory' qui contient également des fichiers et des dossiers. Ce que je veux faire est de déplacer le contenu de 'src Directory' vers 'DST Directory' et d'écraser les fichiers qui existent avec le même nom. Ainsi, par exemple 'Répertoire Srcfichier.txt 'doit être déplacé vers' DST Directory ' et écraser le fichier existant.txt. La même chose s'applique à certains dossiers, en déplaçant un dossier et en fusionnant le contenu avec le même dossier dans 'dst le répertoire'

J'utilise actuellement shutil.move pour déplacer le contenu de src vers DST mais il ne le fera pas si les fichiers existent déjà et il ne fusionnera pas les dossiers; il mettra simplement le dossier dans le dossier existant.

Update: pour rendre les choses un peu plus claires; ce que je fais est de décompresser une archive dans le répertoire Dst, puis de déplacer le contenu du répertoire Src et de le rezipper, mettant à jour efficacement les fichiers dans l'archive zip. Ce sera répété pour l'ajout de nouveaux fichiers ou de nouvelles versions de fichiers etc c'est pourquoi il doit écraser et fusionner

Résolu: j'ai résolu mon problème en utilisant distutils.dir_util.copy_tree(src, dst), cela copie les dossiers et les fichiers du répertoire src vers le répertoire DST et écrase/fusionne où neccesary. L'espoir qui aide à certaines personnes!

J'espère que c'est logique, Merci!

54
demandé sur Artharos 2011-09-14 20:23:30

6 réponses

Utilisez copy() à la place, qui est prêt à écraser les fichiers de destination. Si vous voulez alors que le premier arbre disparaisse, juste rmtree() séparément une fois que vous avez terminé d'itérer dessus.

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

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

Mise à Jour:

Faites un os.walk() sur l'arborescence source. Pour chaque répertoire, Vérifiez s'il existe du côté de la destination, et os.makedirs() s'il est manquant. Pour chaque fichier, il suffit de shutil.copy() et le fichier sera créé ou écrasé, selon le cas.

38
répondu Brandon Rhodes 2011-09-14 17:18:13

Cela passera par le répertoire source, créera tous les répertoires qui n'existent pas déjà dans le répertoire de destination et déplacera les fichiers de la source vers le répertoire de destination:

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)

Tous les fichiers préexistants seront d'abord supprimés (via os.remove) avant d'être remplacés par le fichier source correspondant. Tous les fichiers ou répertoires qui existent déjà dans la destination, mais pas dans la source restera intact.

46
répondu Ray Vega 2016-01-15 12:46:02

Comme aucun des éléments ci-dessus ne fonctionnait pour moi, j'ai donc écrit ma propre fonction récursive. Appelez la fonction copyTree (dir1, dir2) pour fusionner les répertoires. Exécuter sur multi-plates-formes Linux et 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)
6
répondu ALLOY 2014-10-10 03:16:52

Si vous devez également écraser les fichiers avec l'indicateur lecture seule, utilisez ceci:

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)
3
répondu Vit Bernatik 2017-04-20 19:00:34

Ont un coup d'oeil à: os.remove pour supprimer des fichiers existants.

1
répondu phimuemue 2011-09-14 16:37:05

, j'ai eu un problème similaire. Je voulais déplacer des fichiers et des structures de dossiers et écraser les fichiers existants, mais ne pas supprimer tout ce qui se trouve dans la structure du dossier de destination.

Je l'ai résolu en utilisant os.walk(), en appelant récursivement ma fonction et en utilisant shutil.move() sur les fichiers que je voulais écraser et les dossiers qui n'existaient pas.

, Il fonctionne comme shutil.move(), mais avec l'avantage que les fichiers existants ne sont écrasés, mais pas supprimé.

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)
0
répondu the 2015-04-20 14:11:36