Exécutez le code suivant à partir d'un répertoire contenant un répertoire nommé bar
(contenant un ou plusieurs fichiers) et un répertoire nommé baz
(contenant également un ou plusieurs fichiers). Assurez-vous qu'il n'y a pas de répertoire nommé foo
.
import shutil
shutil.copytree('bar', 'foo')
shutil.copytree('baz', 'foo')
Il échouera avec:
$ python copytree_test.py
Traceback (most recent call last):
File "copytree_test.py", line 5, in <module>
shutil.copytree('baz', 'foo')
File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/shutil.py", line 110, in copytree
File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/os.py", line 172, in makedirs
OSError: [Errno 17] File exists: 'foo'
Je veux que cela fonctionne de la même manière que si j'avais tapé:
$ mkdir foo
$ cp bar/* foo/
$ cp baz/* foo/
Dois-je utiliser shutil.copy()
pour copier chaque fichier baz
dans foo
? (Après avoir déjà copié le contenu de 'bar' dans 'foo' avec shutil.copytree()
?) Ou existe-t-il un moyen plus facile / meilleur?
shutil.copytree()
de comportement pour permettre l'écriture dans un répertoire existant, mais il y a certains détails de comportement qui doivent être convenus.Réponses:
Cette limitation de la norme
shutil.copytree
semble arbitraire et ennuyeuse. Solution de contournement:Notez qu'il n'est pas entièrement conforme à la norme
copytree
:symlinks
etignore
paramètres pour le répertoire racine de l'src
arbre;shutil.Error
d'erreurs au niveau racine desrc
;shutil.Error
pour ce sous-arbre au lieu d'essayer de copier d'autres sous-arbres et de lever un seul combinéshutil.Error
.la source
shutil.copytree
fait unos.makedirs(dst)
au début. Aucune partie du code n'aurait réellement un problème avec un répertoire préexistant. Cela doit être changé. Fournir au moins unexist_ok=False
paramètre à l'appeldef copyTree( src, dst, symlinks=False, ignore=None): for item in os.listdir(src): s = os.path.join(src, item) d = os.path.join(dst, item) if os.path.isdir(s): if os.path.isdir(d): self.recursiveCopyTree(s, d, symlinks, ignore) else: shutil.copytree(s, d, symlinks, ignore) else: shutil.copy2(s, d)
distutils.dir_util.copy_tree()
, qui réside également dans le stdlib, n'a pas une telle restriction et se comporte en fait comme prévu. Compte tenu de cela, il n'y a aucune raison impérieuse d'essayer de dérouler votre propre implémentation ( ... généralement cassée ). La réponse de Brendan Abel devrait absolument être la solution acceptée maintenant.Voici une solution qui fait partie de la bibliothèque standard:
Voir cette question similaire.
Copiez le contenu du répertoire dans un répertoire avec python
la source
distutils.errors.DistutilsInternalError: mkpath: 'name' must be a string
, c'est-à-dire qu'il n'accepte pasPosixPath
. Besoin destr(PosixPath)
. Liste de souhaits d'amélioration. En dehors de cette question, je préfère cette réponse.Path
hériter l' objet,str
je suppose, comme la plupart des implémentations antérieures d'objets de chemin orienté objet.distutils.dir_util.copy_tree()
est considéré comme un détail d'implémentation de distutils et non recommandé pour une utilisation publique. La vraie solution devrait êtreshutil.copytree()
d'être améliorée / étendue pour se comporter davantagedistutils.dir_util.copy_tree()
, mais sans ses défauts. En attendant, je continuerai à utiliser des fonctions d'assistance personnalisées similaires à certaines de celles fournies dans d'autres réponses.En légère amélioration sur la réponse d'Atzz à la fonction où la fonction ci-dessus essaie toujours de copier les fichiers de la source vers la destination.
Dans ma mise en œuvre ci-dessus
J'utilise la fonction ci-dessus avec la construction scons. Cela m'a beaucoup aidé car à chaque fois que je compile, je n'ai peut-être pas besoin de copier l'ensemble des fichiers .. mais uniquement les fichiers qui sont modifiés.
la source
if not os.path.exists(d) or os.stat(s).st_mtime - os.stat(d).st_mtime > 1:
Une fusion inspirée par atzz et Mital Vora:
la source
[x for x in lst if x not in excl]
cela ne fait pas la même chose que copytree, qui utilise la correspondance de motifs glob. en.wikipedia.org/wiki/Glob_(programming)Python 3.8 a introduit l'
dirs_exist_ok
argument pourshutil.copytree
:Par conséquent, avec Python 3.8+, cela devrait fonctionner:
la source
dirs_exist_ok=False
par défaut dans copytree, la première tentative de copie n'échouera-t-elle pas?dirs_exist_ok
côté le premier appel pour illustrer la différence (et parce que le répertoire n'existe pas encore dans l'exemple de OP), mais bien sûr vous pouvez l'utiliser si vous le souhaitez.les documents indiquent explicitement que le répertoire de destination ne doit pas exister :
Je pense que votre meilleur pari est
os.walk
le deuxième et tous les répertoires,copy2
répertoires et fichiers conséquents et faire descopystat
répertoires supplémentaires . Après tout, c'est précisément ce quicopytree
fonctionne comme expliqué dans les documents. Ou vous pourriezcopy
etcopystat
chaque répertoire / fichier etos.listdir
au lieu deos.walk
.la source
Ceci est inspiré de la meilleure réponse originale fournie par atzz, je viens d'ajouter la logique de remplacement de fichier / dossier. Donc, il ne fusionne pas réellement, mais supprime le fichier / dossier existant et copie le nouveau:
Décommentez le rmtree pour en faire une fonction de déplacement.
la source
Voici ma version de la même tâche ::
la source
Voici une version inspirée de ce fil qui imite de plus près
distutils.file_util.copy_file
.updateonly
est un booléen si Vrai, ne copiera que les fichiers dont la date de modification est plus récente que les fichiers existants,dst
sauf dans la listeforceupdate
qui les copiera malgré tout.ignore
etforceupdate
attendez-vous à des listes de noms de fichiers ou de dossiers / noms de fichiers relatifs àsrc
et acceptez les caractères génériques de style Unix similaires àglob
oufnmatch
.La fonction renvoie une liste de fichiers copiés (ou serait copiée si elle
dryrun
était True).la source
La solution précédente a un problème qui
src
peut remplacerdst
sans notification ni exception.J'ajoute une
predict_error
méthode pour prévoir les erreurs avant la copie.copytree
principalement basé sur la version de Cyrille Pontvieux.Utiliser
predict_error
pour prédire toutes les erreurs au début est préférable, sauf si vous souhaitez voir une exception levée une par une lors de l'exécutioncopytree
jusqu'à ce que toutes les erreurs soient corrigées.la source
Voici ma passe au problème. J'ai modifié le code source de copytree pour conserver la fonctionnalité d'origine, mais maintenant aucune erreur ne se produit lorsque le répertoire existe déjà. Je l'ai également changé afin qu'il n'écrase pas les fichiers existants mais conserve plutôt les deux copies, une avec un nom modifié, car cela était important pour mon application.
la source
Essaye ça:
la source
Voici une version qui attend une
pathlib.Path
entrée.Notez que cette fonction nécessite Python 3.6, qui est la première version de Python qui
os.listdir()
prend en charge les objets de type chemin en entrée. Si vous devez prendre en charge des versions antérieures de Python, vous pouvez les remplacerlistdir(src)
parlistdir(str(src))
.la source
je suppose que le moyen le plus rapide et le plus simple serait que python appelle les commandes système ...
exemple..
Tar et gzip le répertoire .... décompressez et décompressez le répertoire à l'endroit souhaité.
Ouais?
la source