Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Apprendre Outil d’Inspection de Répertoire | Création d'Applications Console avec Node.js
Développement Backend avec Node.js et Express.js

Outil d’Inspection de Répertoire

Glissez pour afficher le menu

Ce chapitre vous propose un défi : créer une application console avancée nommée DirInspect Pro. Cette application vous permettra d'analyser en profondeur n'importe quel répertoire et d'obtenir des statistiques détaillées sur ses fichiers et sous-répertoires.

Défi

Imaginez un scénario où vous devez naviguer dans un labyrinthe de dossiers contenant des fichiers et des données essentiels. DirInspect Pro est votre allié dans cette exploration, offrant une vue complète de la structure et du contenu du répertoire.

Application obtenue

Préparez-vous à exploiter les fonctionnalités de DirInspect Pro. L'application vous fournira des informations essentielles, telles que :

  • Le nombre total d'éléments ;
  • La taille totale de tous les éléments ;
  • Le nom et la taille du plus grand fichier ;
  • La liste détaillée des noms et tailles de chaque fichier.

Deux chemins à choisir

Deux options s'offrent à vous.

  • La première consiste à relever ce défi de front, en développant vos compétences sans assistance ;
  • La seconde consiste à suivre un guide utile qui garantit votre réussite.

Quel que soit le chemin choisi, une expérience enrichissante vous attend, aboutissant à la création d'une application console captivante et fonctionnelle.

Plan directeur

  • Étape 1 : Importation des modules requis ;
  • Étape 2 : Définition de la fonction getStats ;
  • Étape 3 : Définition de la fonction analyzeFile ;
  • Étape 4 : Définition de la fonction analyzeDirectory ;
  • Étape 5 : Définition et appel de la fonction main ;
  • Conclusion ;
  • Code complet de l'application.

Étape 1 : Importation des modules requis

Pour commencer cette aventure, il vous faut les bons outils. Commencez par importer deux modules clés : fs.promises pour gérer le système de fichiers de manière asynchrone et path pour manipuler efficacement les chemins de fichiers.

const fs = require("fs").promises;
const path = require("path");
Description du code
expand arrow
  • Ligne 1 : importe le module natif fs. La propriété .promises donne accès à l'API basée sur les promesses, permettant d'effectuer des opérations de fichiers asynchrones avec async/await ;
  • Ligne 2 : importe le module natif path. Ce module fournit des utilitaires pour travailler avec les chemins de fichiers et de répertoires, y compris la manipulation et la normalisation des chemins.

Étape 2 : Définir la fonction getStats

La fonction asynchrone getStats prend en argument le chemin d’un fichier ou d’un répertoire et tente d’en récupérer les statistiques à l’aide de fs.stat.

  • En cas de succès, elle retourne les statistiques ;
  • En cas d’erreur, elle affiche un message d’erreur et retourne null.
async function getStats(filePath) {
  try {
    const stats = await fs.stat(filePath);
    return stats;
  } catch (err) {
    console.error("Error getting stats:", err.message);
    return null;
  }
}
Description du code
expand arrow
  • Ligne 1 : déclare une fonction asynchrone nommée getStats qui accepte un paramètre filePath ;
  • Lignes 2, 5 : créent un bloc try...catch utilisé pour la gestion des erreurs lors de l’opération asynchrone ;
  • Ligne 3 : utilise await fs.stat(filePath) pour récupérer des informations sur le fichier spécifié, telles que sa taille, sa date de création et d’autres métadonnées ;
  • Ligne 4 : retourne l’objet stats si l’opération fs.stat() s’effectue avec succès ;
  • Ligne 6 : affiche un message d’erreur dans la console avec console.error() si l’opération échoue ;
  • Ligne 7 : retourne null pour indiquer que les statistiques du fichier n’ont pas pu être récupérées.

Étape 3 : Définir la fonction analyzeFile

La fonction analyzeFile utilise la fonction getStats pour obtenir les statistiques d’un fichier. Si les statistiques sont disponibles (différentes de null), elle retourne un objet contenant le nom du fichier (extrait avec path.basename) et sa taille.

async function analyzeFile(filePath) {
  const stats = await getStats(filePath);
  if (!stats) return null;

  return {
    name: path.basename(filePath),
    size: stats.size,
  };
}
Description du code
expand arrow
  • Ligne 1 : déclare une fonction asynchrone nommée analyzeFile qui accepte un paramètre filePath ;
  • Ligne 2 : utilise await getStats(filePath) pour récupérer les statistiques du fichier pour le chemin fourni ;
  • Ligne 3 : vérifie si stats est falsy. Si les statistiques n'ont pas pu être récupérées, la fonction retourne null ;
  • Lignes 5-8 : crée et retourne un objet contenant le nom et la taille du fichier. Le nom du fichier est extrait avec path.basename(filePath), tandis que la taille est obtenue depuis stats.size.

Étape 4 : Définir la fonction analyzeDirectory

La fonction analyzeDirectory analyse un répertoire et collecte des statistiques complètes sur son contenu. Fonctionnement : elle lit tous les éléments du répertoire à l'aide de fs.readdir. Pour chaque élément :

  • Construit le chemin complet avec path.join ;
  • Utilise getStats pour détecter s'il s'agit d'un fichier ou d'un dossier ;
  • Si c'est un fichier :
    • Appelle analyzeFile pour obtenir { name, size } ;
    • Met à jour les totaux, le plus gros fichier et la liste des fichiers.
  • Si c'est un répertoire :
    • Appelle récursivement analyzeDirectory ;
    • Fusionne les résultats dans les statistiques courantes.
async function analyzeDirectory(directoryPath) {
  let totalItems = 0;
  let totalFiles = 0;
  let totalSize = 0;
  let largestFile = { name: "", size: 0 };
  let fileList = [];

  try {
    const items = await fs.readdir(directoryPath);

    for (const item of items) {
      const itemPath = path.join(directoryPath, item);
      const stats = await getStats(itemPath);
      if (!stats) continue;

      totalItems++;

      if (stats.isFile()) {
        const fileInfo = await analyzeFile(itemPath);
        if (!fileInfo) continue;

        totalFiles++;
        totalSize += fileInfo.size;

        if (fileInfo.size > largestFile.size) {
          largestFile = fileInfo;
        }

        fileList.push(fileInfo);
      } else if (stats.isDirectory()) {
        const subDirectoryStats = await analyzeDirectory(itemPath);

        totalItems += subDirectoryStats.totalItems;
        totalFiles += subDirectoryStats.totalFiles;
        totalSize += subDirectoryStats.totalSize;

        if (subDirectoryStats.largestFile.size > largestFile.size) {
          largestFile = subDirectoryStats.largestFile;
        }

        fileList = fileList.concat(subDirectoryStats.fileList);
      }
    }

    return {
      totalItems,
      totalFiles,
      totalSize,
      largestFile,
      fileList
    };
  } catch (err) {
    console.error("Error analyzing directory contents:", err.message);
    return {
      totalItems: 0,
      totalFiles: 0,
      totalSize: 0,
      largestFile: { name: "", size: 0 },
      fileList: []
    };
  }
}
Description du code
expand arrow
  • Ligne 1 : déclare une fonction asynchrone nommée analyzeDirectory qui accepte un paramètre directoryPath ;

  • Lignes 2-6 : initialise les variables utilisées pour stocker les statistiques du répertoire, y compris le nombre total d'éléments, le nombre total de fichiers, la taille totale, le plus gros fichier et une liste des fichiers analysés ;

  • Ligne 8 : commence un bloc try pour gérer les erreurs potentielles du système de fichiers ;

  • Ligne 9 : lit le contenu du répertoire avec fs.readdir() et stocke le résultat dans le tableau items ;

  • Ligne 11 : commence une boucle for...of pour parcourir chaque élément du répertoire ;

  • Ligne 12 : crée le chemin complet pour l'élément courant avec path.join() ;

  • Ligne 13 : récupère les statistiques pour l'élément courant avec getStats() ;

  • Ligne 14 : saute l'élément courant si ses statistiques n'ont pas pu être récupérées ;

  • Ligne 16 : incrémente totalItems pour chaque fichier ou dossier traité avec succès ;

  • Lignes 18-29 : gestion du traitement des fichiers :

  • Ligne 19 : appelle analyzeFile() pour récupérer le nom et la taille du fichier ;

  • Ligne 20 : saute le fichier si l'analyse échoue ;

    • Lignes 22-23 : met à jour le nombre total de fichiers et la taille totale accumulée ;
    • Lignes 25-27 : met à jour largestFile si le fichier courant est plus grand que le précédent ;
  • Ligne 29 : ajoute les informations du fichier à fileList ;

  • Lignes 30-42 : gestion du traitement des répertoires :

    • Ligne 31 : appelle récursivement analyzeDirectory() pour le sous-répertoire ;
    • Lignes 33-35 : fusionne les statistiques du sous-répertoire dans les totaux courants ;
    • Lignes 37-39 : met à jour largestFile si le sous-répertoire contient un fichier plus volumineux ;
  • Ligne 41 : fusionne les listes de fichiers avec concat() ;

  • Lignes 45-50 : retourne un objet contenant les statistiques finales du répertoire ;

  • Lignes 52-62 : gestion des erreurs en affichant un message et en retournant un objet de statistiques par défaut.

Étape 5 : Définir la fonction main et l’invoquer

La fonction main constitue le point d’entrée du script. Elle spécifie le chemin du répertoire à analyser (dans ce cas, ./docs), appelle la fonction analyzeDirectory pour obtenir les statistiques du répertoire et de son contenu, puis affiche les informations collectées. La fonction affiche :

  • Le nombre total d’éléments ;
  • Le nombre total de fichiers ;
  • La taille totale ;
  • Les détails concernant le plus grand fichier ;
  • La liste des fichiers du répertoire.
async function main() {
  const directoryPath = "./docs";
  const directoryStats = await analyzeDirectory(directoryPath);

  console.log("Directory Analysis:");
  console.log("Total items:", directoryStats.totalItems);
  console.log("Total files:", directoryStats.totalFiles);
  console.log("Total size (bytes):", directoryStats.totalSize);
  console.log(
    "Largest file:",
    directoryStats.largestFile.name,
    "Size:",
    directoryStats.largestFile.size,
    "bytes"
  );

  console.log("\nFile List:");
  for (const file of directoryStats.fileList) {
    console.log(file.name, "Size:", file.size, "bytes");
  }
}

main();
Description du code
expand arrow
  • Ligne 1 : déclare une fonction asynchrone nommée main ;

  • Ligne 2 : définit la variable directoryPath, qui stocke le chemin du répertoire à analyser ;

  • Ligne 3 : appelle analyzeDirectory() avec le directoryPath spécifié et stocke le résultat dans la variable directoryStats en utilisant await ;

  • Lignes 5-17 : affichent les statistiques calculées du répertoire à l’aide de console.log(), incluant le nombre total d’éléments, le nombre total de fichiers, la taille totale et les informations sur le plus grand fichier ;

  • Lignes 18-20 : itèrent sur le tableau fileList stocké dans directoryStats ;

  • affichent le nom et la taille de chaque fichier du répertoire ;

  • Ligne 23 : appelle la fonction main() pour démarrer le processus d’analyse.

Code complet de l’application

const fs = require("fs").promises;
const path = require("path");

async function getStats(filePath) {
  try {
    const stats = await fs.stat(filePath);
    return stats;
  } catch (err) {
    console.error("Error getting stats:", err.message);
    return null;
  }
}

async function analyzeFile(filePath) {
  const stats = await getStats(filePath);
  if (!stats) return null;

  return {
    name: path.basename(filePath),
    size: stats.size
  };
}

async function analyzeDirectory(directoryPath) {
  let totalItems = 0;
  let totalFiles = 0;
  let totalSize = 0;
  let largestFile = { name: "", size: 0 };
  let fileList = [];

  try {
    const items = await fs.readdir(directoryPath);

    for (const item of items) {
      const itemPath = path.join(directoryPath, item);
      const stats = await getStats(itemPath);
      if (!stats) continue;

      totalItems++;

      if (stats.isFile()) {
        const fileInfo = await analyzeFile(itemPath);
        if (!fileInfo) continue;

        totalFiles++;
        totalSize += fileInfo.size;

        if (fileInfo.size > largestFile.size) {
          largestFile = fileInfo;
        }

        fileList.push(fileInfo);
      } else if (stats.isDirectory()) {
        const subDirectoryStats = await analyzeDirectory(itemPath);

        totalItems += subDirectoryStats.totalItems;
        totalFiles += subDirectoryStats.totalFiles;
        totalSize += subDirectoryStats.totalSize;

        if (subDirectoryStats.largestFile.size > largestFile.size) {
          largestFile = subDirectoryStats.largestFile;
        }

        fileList = fileList.concat(subDirectoryStats.fileList);
      }
    }

    return {
      totalItems,
      totalFiles,
      totalSize,
      largestFile,
      fileList
    };
  } catch (err) {
    console.error("Error analyzing directory contents:", err.message);
    return {
      totalItems: 0,
      totalFiles: 0,
      totalSize: 0,
      largestFile: { name: "", size: 0 },
      fileList: []
    };
  }
}

async function main() {
  const directoryPath = "./docs";
  const directoryStats = await analyzeDirectory(directoryPath);

  console.log("Directory Analysis:");
  console.log("Total items:", directoryStats.totalItems);
  console.log("Total files:", directoryStats.totalFiles);
  console.log("Total size (bytes):", directoryStats.totalSize);

  console.log(
    "Largest file:",
    directoryStats.largestFile.name,
    "Size:",
    directoryStats.largestFile.size,
    "bytes"
  );

  console.log("\nFile List:");
  for (const file of directoryStats.fileList) {
    console.log(file.name, "Size:", file.size, "bytes");
  }
}

main();
Tout était clair ?

Comment pouvons-nous l'améliorer ?

Merci pour vos commentaires !

Section 2. Chapitre 10

Demandez à l'IA

expand

Demandez à l'IA

ChatGPT

Posez n'importe quelle question ou essayez l'une des questions suggérées pour commencer notre discussion

Section 2. Chapitre 10
some-alt