web-dev-qa-db-fra.com

Python - Déplace et écrase des fichiers et des dossiers

J'ai un répertoire, "Dst Directory", qui contient des fichiers et des dossiers, et "src Directory", qui contient également des fichiers et des dossiers. Ce que je veux faire, c'est déplacer le contenu de 'src Directory' vers 'Dst Directory' et écraser tous les fichiers existants du même nom. Ainsi, par exemple, 'Src Directory\file.txt' doit être déplacé vers 'Dst Directory \' et remplacer le fichier existant.txt. La même chose s'applique pour certains dossiers, déplacer un dossier et fusionner le contenu avec le même dossier dans 'répertoire dst'

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 ne fusionnera pas les dossiers. il ne vous reste plus qu'à placer le dossier dans le dossier existant.

Mise à jour: pour rendre les choses un peu plus claires; Ce que je fais consiste à décompresser une archive dans le répertoire Dst, puis à y déplacer le contenu du répertoire Src, puis à effectuer une nouvelle procédure de mise à jour et de mise à jour des fichiers dans l'archive Zip. Cela sera répété pour l'ajout de nouveaux fichiers ou de nouvelles versions de fichiers, etc. C'est pourquoi il est nécessaire d'écraser et de 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 dans le répertoire dst et remplace/fusionne le cas échéant. J'espère que cela aide certaines personnes!

J'espère que cela a du sens, merci!

59
Artharos

Utilisez plutôt copy(), qui accepte d'écraser les fichiers de destination. Si vous souhaitez ensuite que le premier arbre disparaisse, il vous suffit de le remplacer par rmtree() une fois que vous avez terminé.

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

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

Mettre à 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, indiquez simplement shutil.copy() et le fichier sera créé ou remplacé, selon le cas.

41
Brandon Rhodes

Cela passe par le répertoire source, crée tous les répertoires qui n'existent pas déjà dans le répertoire de destination et déplace les fichiers de la source au 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):
            # 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)

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 resteront intacts.

50
Ray Vega

Aucune de ces solutions ne fonctionnant pour moi, j’ai donc écrit ma propre fonction récursive. Appelez la fonction copyTree (dir1, dir2) pour fusionner des répertoires. Exécuter sur plusieurs 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
ALLOY

Si vous devez également écraser les fichiers avec le drapeau en 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
Vit Bernatik

Consultez: os.remove pour supprimer les fichiers existants.

1
phimuemue

J'avais un problème similaire. Je voulais déplacer des fichiers et des structures de dossiers et écraser des fichiers existants, mais ne supprimer aucun élément de la structure de dossiers de destination.

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

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

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
the