Copier un dossier en Python avec shutil.copytree()

Le module shutil permet de copier facilement des fichiers mais également des dossiers complets. La fonction shutil.copytree() copie récursivement un dossier avec ses fichiers et ses sous-dossiers. Elle propose plusieurs options permettant notamment de copier vers un dossier existant, d'ignorer certains fichiers ou de gérer les liens symboliques.

1. À propos de shutil.copytree()

La fonction shutil.copytree() appartient au module shutil de la bibliothèque standard de Python. Elle permet de copier une arborescence complète, c'est-à-dire un dossier avec les fichiers et les sous-dossiers qu'il contient.

Il n'est pas nécessaire d'installer le module shutil avec pip. Il suffit de l'importer avant de l'utiliser. Le programme suivant vérifie simplement que le module est disponible.

Sortie :

2. Syntaxe de copytree()

Dans sa forme la plus simple, copytree() reçoit deux arguments : src représente le dossier source et dst le dossier de destination. La fonction dispose également de plusieurs paramètres optionnels.

Sortie :

Une forme plus complète de la fonction peut notamment utiliser symlinks, ignore, copy_function, ignore_dangling_symlinks et dirs_exist_ok.

3. Préparer un dossier pour les exemples

Pour comprendre le fonctionnement de copytree(), nous allons créer un dossier projet contenant un fichier et un sous-dossier. Le module os permet ici de préparer cette petite arborescence.

Sortie :

Nous disposons maintenant du dossier projet, du fichier index.txt et du sous-dossier images contenant lui-même un fichier.

4. Copier simplement un dossier

Pour copier entièrement le dossier projet vers un nouveau dossier copie_projet, nous indiquons simplement les deux chemins à shutil.copytree().

Sortie :

Le dossier copie_projet est créé automatiquement et reçoit une copie de l'ensemble du contenu du dossier source.

5. Copie récursive des sous-dossiers

copytree() effectue une copie récursive. Il n'est donc pas nécessaire de parcourir manuellement les sous-dossiers : leurs fichiers et leurs propres sous-dossiers sont également copiés.

Le programme suivant copie l'arborescence puis vérifie l'existence d'un fichier situé dans un sous-dossier.

Sortie :

La valeur True montre que le sous-dossier images et son fichier info.txt ont bien été copiés.

6. Copier vers un dossier existant

Par défaut, copytree() attend généralement que le dossier de destination n'existe pas encore. Si celui-ci existe, une exception FileExistsError peut être déclenchée.

L'exemple suivant tente de copier le dossier projet vers un dossier backup déjà existant.

Sortie :

Pour autoriser la copie dans une arborescence de destination existante, nous pouvons utiliser le paramètre dirs_exist_ok=True.

7. Utiliser dirs_exist_ok

Le paramètre dirs_exist_ok=True autorise copytree() à copier l'arborescence lorsque le dossier de destination existe déjà. Les fichiers de destination portant le même nom peuvent alors être remplacés par les fichiers copiés.

Sortie :

Cette option est très pratique pour mettre à jour une sauvegarde ou fusionner le contenu du dossier source avec une arborescence existante.

8. Ignorer certains fichiers

Il n'est pas toujours souhaitable de copier tous les fichiers d'un projet. Les fichiers temporaires, les caches ou les journaux peuvent par exemple être exclus. Le paramètre ignore permet de préciser les éléments qui ne doivent pas être copiés.

Le moyen le plus simple consiste généralement à associer ce paramètre à shutil.ignore_patterns().

Sortie :

Tous les fichiers correspondant au motif *.tmp sont ignorés pendant la copie.

9. Utiliser ignore_patterns()

La fonction shutil.ignore_patterns() construit une fonction d'exclusion à partir d'un ou plusieurs motifs. Le caractère * peut notamment représenter plusieurs caractères.

Dans l'exemple suivant, tous les fichiers ayant l'extension .log sont exclus.

Sortie :

Un fichier comme erreurs.log ou application.log ne sera donc pas présent dans la copie.

10. Ignorer plusieurs types de fichiers

ignore_patterns() accepte plusieurs motifs. Nous pouvons ainsi exclure simultanément différentes catégories de fichiers inutiles dans une sauvegarde.

L'exemple suivant ignore les fichiers .tmp, .log et les fichiers compilés Python .pyc.

Sortie :

Les fichiers correspondant à l'un de ces trois motifs ne sont pas copiés dans le dossier backup.

11. Ignorer un dossier

ignore_patterns() peut également exclure des dossiers. Cette possibilité est particulièrement utile pour éviter de copier des répertoires de cache ou des environnements virtuels.

Dans un projet Python, nous pouvons par exemple ignorer __pycache__ et .venv.

Sortie :

Les dossiers portant exactement ces noms ne seront pas reproduits dans l'arborescence de destination lorsqu'ils sont rencontrés.

12. Créer une fonction personnalisée d'exclusion

Lorsque ignore_patterns() n'est pas suffisamment flexible, nous pouvons créer notre propre fonction pour déterminer les fichiers à ignorer. Cette fonction reçoit le chemin du dossier courant et la liste des noms qu'il contient, puis retourne les noms à exclure.

L'exemple suivant ignore tous les fichiers dont le nom commence par temp.

Sortie :

Une fonction personnalisée permet de mettre en place des règles d'exclusion plus complexes que de simples motifs de noms.

13. Copier les liens symboliques

Le paramètre symlinks détermine le traitement des liens symboliques. Avec symlinks=True, les liens symboliques présents dans le dossier source sont reproduits comme liens symboliques dans la destination.

L'exemple suivant active explicitement cette option lors de la copie.

Sortie :

Avec la valeur par défaut symlinks=False, le comportement consiste généralement à copier le contenu vers lequel pointe le lien plutôt que de recréer simplement le lien.

14. Choisir la fonction de copie avec copy_function

Le paramètre copy_function permet de choisir la fonction utilisée pour copier chaque fichier. Par défaut, copytree() utilise shutil.copy2(), qui cherche à conserver les métadonnées prises en charge.

Si ces métadonnées ne sont pas nécessaires, nous pouvons par exemple demander à copytree() d'utiliser shutil.copy().

Sortie :

Le paramètre copy_function permet donc de personnaliser la manière dont les fichiers individuels sont copiés.

15. Récupérer le chemin retourné par copytree()

copytree() retourne le chemin du dossier de destination. Nous pouvons récupérer cette valeur dans une variable afin de l'utiliser ensuite dans le programme.

Sortie :

Cette valeur peut être utile pour effectuer automatiquement d'autres traitements sur le dossier créé.

16. Erreur : le dossier de destination existe déjà

L'une des erreurs les plus fréquentes avec copytree() apparaît lorsque le dossier de destination existe déjà alors que dirs_exist_ok conserve sa valeur par défaut False.

Le programme suivant montre comment intercepter cette erreur.

Sortie possible :

Si nous souhaitons réellement copier dans une arborescence existante, la solution habituelle consiste à utiliser dirs_exist_ok=True.

17. Erreur : le dossier source n'existe pas

Une autre erreur fréquente consiste à fournir à copytree() un chemin source inexistant. Python peut alors déclencher une exception FileNotFoundError.

Nous pouvons vérifier l'existence du dossier avant d'effectuer la copie.

Sortie possible :

La fonction os.path.isdir() permet ici de vérifier que le chemin correspond bien à un dossier existant.

18. Erreur de permission

Une copie peut également échouer lorsque Python ne dispose pas des droits nécessaires pour lire le dossier source ou écrire dans la destination. Une exception PermissionError peut alors être déclenchée.

Le programme suivant intercepte cette erreur afin d'afficher un message plus clair.

Sortie possible :

Dans ce cas, il faut vérifier les permissions du système, le chemin choisi et les droits de l'utilisateur exécutant le programme.

19. Gérer les erreurs avec try et except

Pour rendre un programme plus robuste, nous pouvons regrouper plusieurs traitements d'erreurs dans un bloc try...except. Cela permet de distinguer les principales causes d'échec de la copie.

Sortie possible :

Le type shutil.Error peut notamment regrouper certaines erreurs rencontrées pendant les opérations de copie de l'arborescence.

20. Exemple pratique de sauvegarde d'un projet

Une application très courante de copytree() consiste à créer une sauvegarde d'un projet Python. Nous pouvons exclure les caches, l'environnement virtuel, les journaux et les fichiers temporaires afin d'éviter de copier des données inutiles.

Le programme suivant copie le dossier mon_projet vers backup_projet tout en ignorant plusieurs catégories de fichiers.

Sortie :

Le dossier backup_projet contient ainsi les fichiers utiles du projet sans les caches, l'environnement virtuel et les fichiers temporaires spécifiés.

21. Options importantes de copytree()

src indique le dossier source dont l'arborescence doit être copiée.

dst indique le dossier de destination dans lequel l'arborescence sera reproduite.

symlinks détermine si les liens symboliques doivent être conservés comme liens.

ignore reçoit une fonction permettant d'indiquer les fichiers ou dossiers qui doivent être exclus de la copie.

copy_function permet de choisir la fonction utilisée pour copier chaque fichier. La fonction utilisée par défaut est shutil.copy2().

ignore_dangling_symlinks intervient dans la gestion de certains liens symboliques cassés lorsque les liens ne sont pas conservés comme tels.

dirs_exist_ok autorise, lorsqu'il vaut True, la copie dans une arborescence de destination déjà existante.

22. Remarques Finales

shutil.copytree() copie automatiquement un dossier, ses fichiers et tous ses sous-dossiers.

La copie est récursive : il n'est donc pas nécessaire de parcourir manuellement chaque niveau de l'arborescence.

dirs_exist_ok=True permet de travailler avec une arborescence de destination déjà existante.

shutil.ignore_patterns() constitue une solution simple pour exclure certains fichiers ou dossiers selon leur nom.

Le paramètre ignore peut également recevoir une fonction personnalisée pour créer des règles d'exclusion plus complexes.

Les exceptions comme FileNotFoundError, FileExistsError, PermissionError et shutil.Error permettent de traiter les principales erreurs susceptibles de se produire pendant une copie.

La fonction shutil.copytree() constitue l'une des solutions les plus simples pour copier entièrement un dossier en Python. Elle prend automatiquement en charge les fichiers et les sous-dossiers, ce qui évite de programmer soi-même un parcours récursif de l'arborescence.

Grâce aux paramètres dirs_exist_ok, ignore, symlinks et copy_function, son comportement peut être adapté à de nombreux besoins. Associée à ignore_patterns(), elle devient particulièrement pratique pour créer des sauvegardes de projets en excluant les caches, fichiers temporaires et autres données inutiles.

 


 


Auteur : Younes Derfoufi
Lieu de travail : CRMEF OUJDA
Site Web : www.tresfacile.net
Chaine YouTube : https://www.youtube.com/user/InformatiquesFacile
Me contacter : https://www.tresfacile.net/me-contacter/


Leave a Reply

Your email address will not be published. Required fields are marked *