
Parcourir récursivement une arborescence (os.walk)
Découvrez la fonction 'os.walk()' en Python pour parcourir récursivement une arborescence de répertoires. Explorez tous les fichiers et sous-répertoires d'un répertoire donné, et traitez-les efficacement.
Qu'est-ce qu'un parcours récursif ?
Parcourir une arborescence de répertoires (ou arborescence de fichiers) signifie visiter tous les répertoires et fichiers contenus dans un répertoire donné, y compris tous les sous-répertoires, et les sous-répertoires de ces sous-répertoires, etc., jusqu'à ce qu'il n'y ait plus de sous-répertoires.
Ce type de parcours est appelé *récursif* car il s'applique de manière répétée à chaque sous-répertoire.
Le parcours récursif est une opération courante lorsque vous devez traiter tous les fichiers d'un projet, rechercher des fichiers spécifiques, analyser la structure d'un système de fichiers, etc.
En Python, la fonction `os.walk()` du module `os` facilite grandement le parcours récursif.
os.walk() : la fonction pour parcourir une arborescence
La fonction `os.walk()` génère une séquence de tuples pour chaque répertoire rencontré lors du parcours de l'arborescence.
Syntaxe :
import os
for repertoire_courant, sous_repertoires, fichiers in os.walk(repertoire_racine):
# Traiter le répertoire courant, ses sous-répertoires et ses fichiers
# ...- `repertoire_racine` : Le chemin d'accès au répertoire racine à partir duquel le parcours doit commencer.
- `os.walk(repertoire_racine)` retourne un *générateur*. A chaque itération, le générateur produit un tuple contenant trois éléments :
- `repertoire_courant` : Le chemin d'accès (sous forme de chaîne) du répertoire en cours de traitement.
- `sous_repertoires` : Une *liste* de chaînes de caractères, contenant les noms des sous-répertoires du répertoire courant (sans leur chemin complet).
- `fichiers` : Une *liste* de chaînes de caractères, contenant les noms des fichiers du répertoire courant (sans leur chemin complet).
La boucle `for` parcourt donc tous les répertoires et fichiers de l'arborescence, en commençant par le répertoire racine.
Exemple de base : afficher tous les fichiers et répertoires
Voici un exemple simple qui affiche le chemin complet de tous les fichiers et répertoires d'une arborescence :
import os
def parcourir_arborescence(repertoire_racine):
"""Parcourt récursivement une arborescence et affiche le chemin de chaque fichier et répertoire."""
for repertoire_courant, sous_repertoires, fichiers in os.walk(repertoire_racine):
for nom in sous_repertoires:
print(os.path.join(repertoire_courant, nom)) # Affiche le chemin complet du répertoire
for nom in fichiers:
print(os.path.join(repertoire_courant, nom)) # Affiche le chemin complet du fichier
# Exemple d'utilisation (remplacez par le chemin de votre choix)
# parcourir_arborescence('.') #Pour parcourir le repertoire courant
Dans cet exemple :
- La fonction `parcourir_arborescence` prend le répertoire racine en argument.
- La boucle `for` utilise `os.walk` pour parcourir l'arborescence.
- A chaque itération, `repertoire_courant`, `sous_repertoires`, et `fichiers` sont mis à jour avec les informations du répertoire courant.
- Deux boucles `for` internes parcourent la liste des sous-répertoires et la liste des fichiers, respectivement.
- `os.path.join(repertoire_courant, nom)` est utilisé pour construire le chemin complet de chaque fichier et répertoire.
Options de os.walk() : topdown, onerror, et followlinks
`os.walk()` accepte quelques arguments optionnels :
- `topdown=True` (par défaut) : Si `True`, le parcours se fait du haut vers le bas (d'abord le répertoire racine, puis ses sous-répertoires, etc.). Si `False`, le parcours se fait du bas vers le haut (d'abord les sous-répertoires les plus profonds, puis leurs parents, etc.).
- `onerror=None` : Une fonction optionnelle qui sera appelée en cas d'erreur (par exemple, si `os.walk` ne peut pas accéder à un répertoire). Si `onerror` est `None` (par défaut), les erreurs sont ignorées. La fonction `onerror` reçoit l'objet exception `OSError` en argument.
- `followlinks=False` : Si `True`, `os.walk` suivra les liens symboliques qui pointent vers des répertoires. Par défaut, les liens symboliques ne sont pas suivis. Attention aux boucles infinies si vous activez cette option et que vous avez des liens symboliques qui pointent vers des ancêtres du répertoire courant !
Exemple (parcours du bas vers le haut, avec gestion des erreurs) :
import os
def gestionnaire_erreurs(erreur):
print(f"Erreur lors du parcours : {erreur}")
for root, dirs, files in os.walk('.', topdown=False, onerror=gestionnaire_erreurs):
# ... (traitement) ...Modifier la liste des sous-répertoires : élaguer l'arborescence
Un aspect puissant de `os.walk()` est que vous pouvez *modifier la liste `sous_repertoires` en place* à l'intérieur de la boucle `for`. Cela vous permet de contrôler quels sous-répertoires seront visités par `os.walk()`.
Par exemple, si vous voulez ignorer certains sous-répertoires (par exemple, les répertoires cachés, ou les répertoires de sauvegarde), vous pouvez les supprimer de la liste `sous_repertoires`.
Exemple (ignorer les répertoires commençant par un point) :
import os
for repertoire_courant, sous_repertoires, fichiers in os.walk('.'):
# Supprimer les répertoires commençant par un point de la liste des sous-répertoires
sous_repertoires[:] = [d for d in sous_repertoires if not d.startswith('.')]
# ... (traitement) ...Dans cet exemple, la ligne `sous_repertoires[:] = ...` modifie la liste `sous_repertoires` *en place*. C'est important : vous devez modifier la liste elle-même, pas créer une nouvelle liste. `os.walk()` utilise la liste modifiée pour déterminer quels sous-répertoires visiter.
Cette technique permet d'élaguer l'arborescence et d'optimiser le parcours en ignorant les parties qui ne vous intéressent pas.
Exemple concret : rechercher des fichiers avec une extension spécifique
Voici un exemple concret qui utilise `os.walk()` pour rechercher tous les fichiers avec une extension spécifique (par exemple, `.py`) dans une arborescence :
import os
def rechercher_fichiers(repertoire_racine, extension):
"""Recherche tous les fichiers avec une extension donnée dans une arborescence."""
fichiers_trouves = []
for repertoire_courant, sous_repertoires, fichiers in os.walk(repertoire_racine):
for nom_fichier in fichiers:
if nom_fichier.endswith(extension):
chemin_complet = os.path.join(repertoire_courant, nom_fichier)
fichiers_trouves.append(chemin_complet)
return fichiers_trouves
# Utilisation
fichiers_python = rechercher_fichiers(".", ".py") # Recherche les fichiers .py à partir du répertoire courant
for fichier in fichiers_python:
print(fichier)Cet exemple montre comment combiner `os.walk()` avec une simple condition (`endswith`) pour effectuer une recherche de fichiers ciblée.