CodeGym /Cours /C# SELF /Opérations en masse sur les fichiers

Opérations en masse sur les fichiers

C# SELF
Niveau 40 , Leçon 4
Disponible

1. Introduction

Imagine un archive de photos sur plusieurs années — des milliers de fichiers dans un seul dossier (classique chez les utilisateurs Windows), et maintenant imagine la tâche : copier seulement les fichiers .jpg qui ont été créés cette année dans un dossier séparé pour traitement. Ou tu dois renommer tous les rapports avec le préfixe "old_" pour différencier l'ancienne et la nouvelle version. Même si tu n'es pas fan des archives photo, les opérations en masse sont utiles dans presque tous les projets de traitement de données, logs, backups ou automatisation. Elles tombent aussi souvent en entretien technique !

Les opérations en masse sont un super prétexte pour maîtriser :

  • Boucles et LINQ pour parcourir le contenu des répertoires
  • Pratique de la gestion des chemins (Path)
  • Bases du filtrage, de la recherche, du renommage par motif
  • Points importants : sécurité, erreurs, écrasements

Allons-y — que la force soit avec toi pour dompter le chaos des fichiers !

2. Copie en masse de fichiers

Principes : comment ça marche

Pour une opération en masse il faut généralement :

  1. Obtenir la liste des fichiers voulus (par exemple, tous les .txt dans un dossier)
  2. Pour chaque fichier effectuer l'action nécessaire (copier, supprimer, etc.)

On peut réaliser ça avec :

  • Directory.GetFiles() — récupérer la liste des fichiers,
  • Une boucle foreach — parcourir chaque fichier et effectuer l'opération voulue.

Exemple : copier tous les fichiers .txt d'un dossier vers un autre


string sourceDir = @"C:\Source";
string destDir = @"C:\Target";

// On récupère la liste de tous les fichiers .txt dans le dossier source
string[] txtFiles = Directory.GetFiles(sourceDir, "*.txt");

foreach (string srcPath in txtFiles)
{
    // On récupère uniquement le nom de fichier à partir du chemin complet
    string fileName = Path.GetFileName(srcPath);

    // On construit le chemin complet pour le fichier dans le dossier cible
    string destPath = Path.Combine(destDir, fileName);

    // On copie le fichier
    File.Copy(srcPath, destPath, overwrite: true); // overwrite - si le fichier existe déjà, remplacer
    Console.WriteLine($"Copied: {fileName}");
}

Console.WriteLine("Tous les fichiers .txt ont été copiés avec succès !");

Remarque : dans cet exemple on utilise le filtre "*.txt" — c'est un motif de recherche de noms de fichiers, comme sous Windows.

Visualisation (schéma)

+----------------+     [*.txt]     +----------------+
|   C:\Source    | ---filter-----> |   C:\Target    |
| a.txt          |   foreach +     |                |
| b.txt          | --copy--------> | a.txt (copied) |
| c.jpg          |                | b.txt (copied) |
+----------------+                +----------------+
(les fichiers .jpg sont ignorés, seuls les .txt sont copiés)

3. Suppression en masse de fichiers

La suppression en masse est une opération très courante. Par exemple, il faut souvent nettoyer les fichiers temporaires, supprimer automatiquement les vieux logs ou des photos jpg dont on n'a plus besoin.

Exemple : supprimer tous les fichiers plus vieux que 30 jours


string dir = @"C:\MyLogs";
int daysOld = 30;

DirectoryInfo di = new DirectoryInfo(dir);
// On obtient tous les fichiers dans le dossier
foreach (FileInfo file in di.GetFiles())
{
    // On vérifie la date de dernière modification
    if (file.LastWriteTime < DateTime.Now.AddDays(-daysOld))
    {
        file.Delete();
        Console.WriteLine($"Supprimé : {file.Name}");
    }
}

Astuce : FileInfo.LastWriteTime — hyper pratique pour tester "plus ancien que N jours".

4. Renommage en masse de fichiers

Parfois il faut renommer plein de fichiers selon un motif. Par exemple, ajouter un préfixe commun, changer des extensions, ou simplement numéroter tout ça. En .NET c'est le même principe — on récupère la liste des fichiers, puis on renomme avec File.Move().

Exemple : ajouter le préfixe "old_" à tous les fichiers .docx


string dir = @"C:\Reports";

string[] docxFiles = Directory.GetFiles(dir, "*.docx");
foreach (string oldPath in docxFiles)
{
    string dirPath = Path.GetDirectoryName(oldPath)!;
    string fileName = Path.GetFileName(oldPath);
    string newPath = Path.Combine(dirPath, "old_" + fileName);

    // On renomme (en pratique, c'est un déplacement "dans le même dossier avec un nouveau nom")
    File.Move(oldPath, newPath);
    Console.WriteLine($"Renommé : {fileName} -> old_{fileName}");
}

Point important : si le dossier contient déjà un fichier avec le nouveau nom, une exception sera levée. On peut la gérer via try-catch si nécessaire.

5. Copier des répertoires entiers avec leur contenu

Pour des opérations simples sur un seul dossier il n'y a pas de méthode "copier tout le dossier" en une ligne (Directory.Copy n'existe pas — c'est un piège pour les Jedi !). Il faut copier manuellement :

  1. Créer le dossier cible (s'il n'existe pas)
  2. Copier tous les fichiers (voir l'exemple qu'on connaît)
  3. Copier récursivement tous les sous-dossiers (chacun traité comme une nouvelle tâche de copie)

Fonction universelle : copie récursive d'un dossier


using System;
using System.IO;

class Program
{
    static void CopyDirectory(string sourceDir, string destDir, bool overwrite = true)
    {
        // On crée le dossier s'il n'existe pas
        Directory.CreateDirectory(destDir);

        // On copie tous les fichiers
        foreach (string filePath in Directory.GetFiles(sourceDir))
        {
            string fileName = Path.GetFileName(filePath);
            string destFile = Path.Combine(destDir, fileName);
            File.Copy(filePath, destFile, overwrite);
        }

        // On copie tous les sous-dossiers (récursivement)
        foreach (string subDir in Directory.GetDirectories(sourceDir))
        {
            string dirName = Path.GetFileName(subDir);
            string destSubDir = Path.Combine(destDir, dirName);
            CopyDirectory(subDir, destSubDir, overwrite);
        }
    }

    static void Main()
    {
        string source = @"C:\Archive2023";
        string target = @"D:\Backup2023";
        CopyDirectory(source, target);
        Console.WriteLine("Répertoire copié avec succès !");
    }
}

Schéma

            CopyDirectory(A, B)
               /          \
      copy files        foreach subDir -> CopyDirectory(subDir, destSubDir)

6. Filtrage, recherche et traitement en masse

Supposons que tu veuilles non seulement parcourir un dossier, mais filtrer selon plusieurs critères : par exemple, seulement les images dont la taille dépasse 5 Mo et qui ont été créées en 2024 ! Pour ça il est pratique de combiner LINQ avec les classes du système de fichiers.

Exemple : afficher les noms des images volumineuses et récentes


string dir = @"C:\Pictures";

var filtered = new DirectoryInfo(dir)
    .GetFiles("*.jpg")
    .Where(f => f.Length > 5_000_000 && f.CreationTime.Year == 2024);

foreach (var file in filtered)
{
    Console.WriteLine($"{file.Name} ({file.Length / 1024 / 1024} Mo)");
}

Dans cet exemple on utilise LINQ pour chaîner les filtres — et on écrit du code réaliste qu'on retrouve en production.

7. Parcours des dossiers imbriqués : récursion et itération

Souvent il faut traiter non seulement un répertoire, mais toute son arborescence (par exemple, supprimer tous les fichiers temporaires dans toute la structure). Les méthodes de récupération de fichiers (Directory.GetFiles et DirectoryInfo.GetFiles) ont une variante avec le paramètre spécial SearchOption.AllDirectories, qui s'en occupe pour toi !

Exemple : trouver et supprimer tous les fichiers .tmp dans tous les sous-dossiers


string root = @"D:\BigFolder";
string[] tmpFiles = Directory.GetFiles(root, "*.tmp", SearchOption.AllDirectories);

foreach (string file in tmpFiles)
{
    File.Delete(file);
    Console.WriteLine($"Supprimé : {file}");
}
Console.WriteLine("Tous les fichiers temporaires ont été supprimés.");

Attention : fais gaffe avec ce flag — il peut trouver des fichiers même dans des imbriquations très profondes !

8. Création en masse de fichiers et dossiers

Parfois la tâche est inverse — créer automatiquement une arborescence ou générer beaucoup de fichiers.

Exemple : création de 10 dossiers et 10 fichiers dans chacun


string root = @"C:\GeneratedFolders";

for (int i = 1; i <= 10; i++)
{
    string subDir = Path.Combine(root, $"Folder_{i}");
    Directory.CreateDirectory(subDir);

    for (int j = 1; j <= 10; j++)
    {
        string filePath = Path.Combine(subDir, $"File_{j}.txt");
        File.WriteAllText(filePath, $"Ceci est le fichier numéro {j} dans le dossier {i}");
    }
}

Console.WriteLine("Dossiers et fichiers créés !");

Astuce : c'est un moyen rapide de préparer une infra de test, de générer des données factices pour les tests, l'apprentissage, etc.

9. Déplacement en masse de fichiers

Comme pour la copie, mais on utilise File.Move à la place de File.Copy. Pratique pour trier des fichiers dans des dossiers.

Exemple : trier les fichiers par extension

Imaginons : dans un dossier il y a plein de types de fichiers, et tu veux les répartir dans des dossiers .jpg, .pdf, .docx, etc.


string source = @"C:\Downloads";
string[] files = Directory.GetFiles(source);

foreach (string path in files)
{
    string ext = Path.GetExtension(path).TrimStart('.').ToUpper(); // "JPG", "PDF", "DOCX"
    if (string.IsNullOrEmpty(ext)) ext = "OTHER";
    string destDir = Path.Combine(source, ext);

    Directory.CreateDirectory(destDir); // pas grave si ça existe déjà

    string fileName = Path.GetFileName(path);
    string destPath = Path.Combine(destDir, fileName);

    if (!File.Exists(destPath))
    {
        File.Move(path, destPath);
        Console.WriteLine($"Déplacé : {fileName} -> {destDir}");
    }
    else
    {
        Console.WriteLine($"Le fichier existe déjà dans {destDir}, on passe : {fileName}");
    }
}

Les fichiers seront rangés "par boîte", et tu te sentiras comme la Marie Kondo digitale.

10. Erreurs typiques et subtilités des opérations en masse

Quand tu travailles sur des centaines de fichiers, des détails intéressants apparaissent.

Par exemple, certains fichiers peuvent être ouverts par une autre application — tenter de les supprimer ou copier provoquera une erreur. Il arrive aussi qu'un fichier existe déjà dans le dossier cible avec le même nom. Si le code ne prévoit pas d'écrasement, une exception sera levée. Parfois tu peux ne pas avoir les droits sur certains fichiers ou dossiers, ou supprimer quelque chose d'important par erreur en mode récursif.

L'erreur classique est d'exécuter les opérations sans gestion d'erreurs : si un plantage survient au milieu (par exemple, absence de droits sur un fichier), la boucle s'arrêtera et les fichiers suivants ne seront pas traités. Pour des opérations fiables on met généralement un try-catch à l'intérieur de la boucle, afin de sauter le fichier problématique et continuer le reste.

Et n'oublie pas les paramètres d'écrasement : là où c'est pertinent, utilise overwrite: true dans File.Copy, et pour les renommages/déplacements vérifie d'avance l'existence du fichier cible ou adopte une stratégie de résolution de conflits (ajout d'un suffixe, passer, journaliser).

1
Étude/Quiz
Création et suppression de fichiers, niveau 40, leçon 4
Indisponible
Création et suppression de fichiers
Gestion des fichiers et des dossiers
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION