Listing Récursif de Fichiers
Un peu d'histoire et de contexte
Les systèmes de fichiers hiérarchiques ont été introduits dans les années 1960 avec UNIX. Cette structure en arbre permet d'organiser les données de manière logique : un dossier peut contenir des fichiers et d'autres dossiers, créant ainsi une structure récursive naturelle.
Cette organisation est fondamentale dans tous les systèmes d'exploitation modernes (Windows, Linux, macOS) et correspond parfaitement à un problème résolu par récursivité.
En pratique, de nombreux outils utilisent ce principe : les commandes ls -R (Linux), tree (Windows/Linux), les indexeurs de fichiers, les moteurs de recherche de bureau, et même les outils de sauvegarde qui doivent parcourir l'ensemble d'une arborescence.
Définition algorithmique
Le parcours récursif d'une arborescence de fichiers est un exemple classique de parcours en profondeur (Depth-First Search) d'une structure arborescente.
Structure de données
Un système de fichiers peut être modélisé comme un arbre où :
- Les feuilles sont les fichiers
- Les noeuds internes sont les dossiers
- Chaque noeud peut avoir 0 ou plusieurs enfants
Cas de base
Le cas de base se produit lorsqu'on atteint un fichier :
Si l'élément est un fichier :
Afficher le nom du fichier
TerminerCas récursif
Le cas récursif se produit lorsqu'on atteint un dossier :
Si l'élément est un dossier :
Afficher le nom du dossier
Pour chaque élément dans le dossier :
Appeler récursivement la fonction sur cet élémentAlgorithme général
Fonction ListeFichiers(chemin, niveau_indentation)
Si chemin est un fichier :
Afficher indentation + nom du fichier
Sinon si chemin est un dossier :
Afficher indentation + nom du dossier
Pour chaque élément dans le dossier :
ListeFichiers(élément, niveau_indentation + 1)Exemple d'arborescence
Considérons la structure suivante :
Projet/
├── src/
│ ├── Program.cs
│ └── Utils.cs
├── tests/
│ └── TestUtils.cs
└── README.mdLe parcours récursif explorera :
- Projet/ (dossier)
- src/ (dossier)
- Program.cs (fichier - cas de base)
- Utils.cs (fichier - cas de base)
- tests/ (dossier)
- TestUtils.cs (fichier - cas de base)
- README.md (fichier - cas de base)
Propriétés importantes
- Profondeur : La profondeur maximale correspond au nombre de niveaux de dossiers imbriqués
- Ordre de parcours : L'ordre dépend de l'implémentation (alphabétique, ordre du système de fichiers, etc.)
- Terminaison : Garantie par le fait qu'un système de fichiers sain ne contient pas de cycles
Objectif
Implémenter une fonction récursive en C# qui liste tous les fichiers et dossiers à partir d'un répertoire donné.
Consignes par étapes
Étape 1 : Comprendre les classes du framework
En C#, vous aurez besoin des classes suivantes du namespace System.IO :
Directory.Exists(chemin): vérifie si un dossier existeFile.Exists(chemin): vérifie si un fichier existeDirectory.GetFiles(chemin): retourne un tableau de chemins de fichiersDirectory.GetDirectories(chemin): retourne un tableau de chemins de sous-dossiersPath.GetFileName(chemin): extrait le nom d'un fichier ou dossier depuis son chemin complet
Étape 2 : Créer la méthode récursive de base
- Créez une méthode
static void ListerFichiers(string chemin) - Implémentez le cas de base : si c'est un fichier, affichez son nom
- Implémentez le cas récursif : si c'est un dossier, listez son contenu puis appelez récursivement sur chaque élément
Étape 3 : Améliorer l'affichage avec l'indentation
- Ajouter un paramètre
int niveauà votre méthode :ListerFichiers(string chemin, int niveau = 0) - Utiliser ce niveau pour créer une indentation visuelle (par exemple :
new string(' ', niveau * 2)) - Différenciez visuellement les dossiers des fichiers (par exemple :
[D]pour dossier,[F]pour fichier)
Étape 4 : Gestion des erreurs
Ajouter une gestion des exceptions car certains dossiers peuvent être inaccessibles (permissions insuffisantes) :
- Utiliser un bloc
try-catchpour capturer lesUnauthorizedAccessException - Afficher un message approprié si l'accès est refusé
Étape 5 : Tester la fonction
Dans votre Main() :
- Créer un dossier de test avec quelques sous-dossiers et fichiers
- Appeler la fonction sur ce dossier
- Tester également sur un dossier système (par exemple : le dossier temporaire)
Questions de réflexion
Condition de terminaison : Qu'est-ce qui garantit que votre fonction récursive s'arrêtera toujours ? Que se passerait-il en présence de liens symboliques circulaires ?
Ordre de parcours : Dans quel ordre les fichiers et dossiers sont-ils visités ? Comment modifier cet ordre (par exemple, pour trier alphabétiquement) ?
Comparaison itératif/récursif : Implémenter la même fonctionnalité de manière itérative avec une pile (Stack) ou une liste... ? Quels seraient les avantages et inconvénients ?
Cas limites : Que se passe-t-il si :
- Le chemin fourni n'existe pas ?
- Le dossier est vide ?
- La profondeur est très importante (ex: 1000 niveaux) ?
Extension pratique : Comment modifier la fonction pour :
- Ne lister que les fichiers d'une certaine extension (.cs, .txt) ?
- Calculer la taille totale de tous les fichiers ?
- Compter le nombre de fichiers et de dossiers ?
Pour aller plus loin (optionnel)
- Ajoutez un paramètre pour limiter la profondeur maximale de récursion
- Implémentez un filtre avec des expressions régulières pour ne lister que certains fichiers
- Calculez et affichez la taille de chaque fichier
- Créez une version qui retourne une structure de données (arbre) plutôt que d'afficher directement
- Implémentez un système de statistiques (nombre total de fichiers, taille totale, fichier le plus volumineux, etc.)
- Comparez les performances entre
Directory.GetFileSystemEntries()et l'approche avecGetFiles()+GetDirectories()
Exemple de résultat
[D] MonProjet
[D] src
[F] Program.cs
[F] Utils.cs
[D] tests
[F] TestProgram.cs
[F] README.md
[F] MonProjet.csproj