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.
- À propos de shutil.copytree()
- Syntaxe de copytree()
- Préparer un dossier pour les exemples
- Copier simplement un dossier
- Copie récursive des sous-dossiers
- Copier vers un dossier existant
- Utiliser dirs_exist_ok
- Ignorer certains fichiers
- Utiliser ignore_patterns()
- Ignorer plusieurs types de fichiers
- Ignorer un dossier
- Créer une fonction personnalisée d'exclusion
- Copier les liens symboliques
- Choisir la fonction de copie avec copy_function
- Récupérer le chemin retourné par copytree()
- Erreur : le dossier de destination existe déjà
- Erreur : le dossier source n'existe pas
- Erreur de permission
- Gérer les erreurs avec try et except
- Exemple pratique de sauvegarde d'un projet
- Options importantes de copytree()
- Remarques Finales
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.
1 2 | import shutil print("Module shutil disponible") |
Sortie :
1 | Module shutil disponible |
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.
1 | shutil.copytree(src, dst) |
Sortie :
1 | Le dossier dst est créé avec le contenu de src. |
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.
1 2 3 4 5 6 7 | import os os.makedirs("projet/images", exist_ok=True) with open("projet/index.txt", "w", encoding="utf-8") as fichier: fichier.write("Projet Python") with open("projet/images/info.txt", "w", encoding="utf-8") as fichier: fichier.write("Dossier images") print("Dossier projet créé") |
Sortie :
1 | Dossier projet créé |
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().
1 2 3 | import shutil shutil.copytree("projet", "copie_projet") print("Dossier copié") |
Sortie :
1 | Dossier copié |
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.
1 2 3 4 | import os import shutil shutil.copytree("projet", "backup") print(os.path.exists("backup/images/info.txt")) |
Sortie :
1 | True |
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.
1 2 3 4 5 6 7 | import os import shutil os.makedirs("backup", exist_ok=True) try: shutil.copytree("projet", "backup") except FileExistsError: print("Le dossier de destination existe déjà") |
Sortie :
1 | Le dossier de destination existe déjà |
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.
1 2 3 | import shutil shutil.copytree("projet", "backup", dirs_exist_ok=True) print("Copie terminée") |
Sortie :
1 | Copie terminée |
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().
1 2 3 | import shutil shutil.copytree("projet", "copie_projet", ignore=shutil.ignore_patterns("*.tmp")) print("Copie terminée sans les fichiers .tmp") |
Sortie :
1 | Copie terminée sans les fichiers .tmp |
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.
1 2 3 | import shutil shutil.copytree("projet", "backup", ignore=shutil.ignore_patterns("*.log")) print("Les fichiers .log ont été ignorés") |
Sortie :
1 | Les fichiers .log ont été ignorés |
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.
1 2 3 | import shutil shutil.copytree("projet", "backup", ignore=shutil.ignore_patterns("*.tmp", "*.log", "*.pyc")) print("Copie terminée") |
Sortie :
1 | Copie terminée |
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.
1 2 3 | import shutil shutil.copytree("projet", "backup", ignore=shutil.ignore_patterns("__pycache__", ".venv")) print("Dossiers inutiles ignorés") |
Sortie :
1 | Dossiers inutiles ignorés |
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.
1 2 3 4 5 | import shutil def ignorer_temp(dossier, noms): return [nom for nom in noms if nom.startswith("temp")] shutil.copytree("projet", "backup", ignore=ignorer_temp) print("Fichiers temporaires ignorés") |
Sortie :
1 | Fichiers temporaires ignorés |
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.
1 2 3 | import shutil shutil.copytree("projet", "backup", symlinks=True) print("Copie terminée avec conservation des liens symboliques") |
Sortie :
1 | Copie terminée avec conservation des liens symboliques |
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().
1 2 3 | import shutil shutil.copytree("projet", "backup", copy_function=shutil.copy) print("Copie réalisée avec shutil.copy()") |
Sortie :
1 | Copie réalisée avec shutil.copy() |
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.
1 2 3 | import shutil destination = shutil.copytree("projet", "copie_projet") print("Destination :", destination) |
Sortie :
1 | Destination : copie_projet |
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.
1 2 3 4 5 | import shutil try: shutil.copytree("projet", "backup") except FileExistsError: print("Erreur : le dossier backup existe déjà") |
Sortie possible :
1 | Erreur : le dossier backup existe déjà |
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.
1 2 3 4 5 6 7 8 | import os import shutil source = "mon_projet" if os.path.isdir(source): shutil.copytree(source, "backup") print("Copie terminée") else: print("Le dossier source n'existe pas") |
Sortie possible :
1 | Le dossier source n'existe pas |
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.
1 2 3 4 5 6 | import shutil try: shutil.copytree("projet", "backup") print("Copie terminée") except PermissionError: print("Permission refusée") |
Sortie possible :
1 | Permission refusée |
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.
1 2 3 4 5 6 7 8 9 10 11 12 | import shutil try: shutil.copytree("projet", "backup") print("Copie réussie") except FileNotFoundError: print("Le dossier source est introuvable") except FileExistsError: print("Le dossier de destination existe déjà") except PermissionError: print("Permission refusée") except shutil.Error as erreur: print("Erreur de copie :", erreur) |
Sortie possible :
1 | Copie réussie |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import shutil shutil.copytree( "mon_projet", "backup_projet", ignore=shutil.ignore_patterns( "__pycache__", ".venv", "*.pyc", "*.log", "*.tmp" ), dirs_exist_ok=True ) print("Sauvegarde du projet terminée") |
Sortie :
1 | Sauvegarde du projet terminée |
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/


