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, c’est déplacer le contenu de ‘src Directory’ vers ‘Dst Directory’ et remplacer tous les fichiers existant avec le même nom. Ainsi, par exemple, ‘Src Directory \ file.txt’ doit être déplacé dans ‘Dst Directory \’ et remplacer le fichier.txt existant. Il en va de même pour certains dossiers, en déplaçant un dossier et en fusionnant le contenu avec le même dossier dans le «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 il ne fusionnera pas les dossiers; il suffit de mettre le dossier dans le dossier existant.

Mise à jour: pour rendre les choses un peu plus claires; Ce que je fais, c’est de décompresser une archive dans le répertoire Dst, puis de déplacer le contenu du répertoire Src et de procéder à la modification, en mettant à jour efficacement les fichiers de l’archive zip. Cela sera répété pour l’ajout de nouveaux fichiers ou de nouvelles versions de fichiers, ce qui explique 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 écrase / fusionne là où nécessaire. J’espère que ça aide certaines personnes!

J’espère que c’est logique, merci!

Utilisez plutôt copy() , qui accepte de remplacer les fichiers de destination. Si vous voulez que le premier arbre disparaisse, rmtree() séparément une fois l’itération terminée.

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

Cela parcourra le répertoire source, créera tous les répertoires qui n’existent pas encore dans le répertoire de destination et déplace 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) 

Tout fichier préexistant sera d’abord supprimé (via os.remove ) avant d’être remplacé par le fichier source correspondant. Tous les fichiers ou répertoires qui existent déjà dans la destination mais pas dans la source restront intacts.

Comme rien de tout cela 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écutez 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) 

Si vous devez également écraser des fichiers avec un indicateur 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) 

Regardez: os.remove pour supprimer les fichiers existants.

J’avais 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.

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)