Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Impara Strumento di Ispezione delle Directory | Creazione di Applicazioni Console con Node.js
Sviluppo Backend con Node.js ed Express.js

Strumento di Ispezione delle Directory

Scorri per mostrare il menu

Questo capitolo ti propone una sfida: creare un'app console avanzata chiamata DirInspect Pro. Questa applicazione ti permetterà di analizzare a fondo qualsiasi directory e ottenere statistiche dettagliate sui suoi file e sottodirectory.

Sfida

Immagina uno scenario in cui devi orientarti in un labirinto di cartelle contenenti file e dati cruciali. DirInspect Pro è il tuo alleato in questo percorso, fornendo una panoramica completa della struttura e dei contenuti della directory.

L'applicazione finale

Preparati a sfruttare le funzionalità di DirInspect Pro. L'applicazione ti fornirà informazioni fondamentali, come:

  • Il numero totale di elementi;
  • La dimensione complessiva di tutti gli elementi;
  • Il nome e la dimensione del file più grande;
  • L'elenco dettagliato dei nomi e delle dimensioni dei singoli file.

Due percorsi tra cui scegliere

Hai davanti a te due percorsi.

  • Il primo consiste nell'affrontare questa sfida direttamente, affinando le tue competenze senza alcuna guida;
  • Il secondo consiste nel seguire una guida utile che garantisce il successo.

Qualunque percorso tu scelga, ti aspetta un viaggio gratificante che culminerà nella creazione di un'app console coinvolgente e funzionale.

Piano principale

  • Passo 1: Importazione dei moduli necessari;
  • Passo 2: Definizione della funzione getStats;
  • Passo 3: Definizione della funzione analyzeFile;
  • Passo 4: Definizione della funzione analyzeDirectory;
  • Passo 5: Definizione e invocazione della funzione main;
  • Conclusione;
  • Codice completo dell'app.

Passo 1: Importazione dei moduli necessari

Per intraprendere questa attività, sono necessari gli strumenti giusti. Inizia importando due moduli chiave: fs.promises per gestire il file system in modo asincrono e path per gestire efficacemente i percorsi dei file.

const fs = require("fs").promises;
const path = require("path");
Descrizione del codice
expand arrow
  • Riga 1: importa il modulo integrato fs. La proprietà .promises fornisce accesso all'API basata su promesse, consentendo operazioni asincrone sui file utilizzando async/await;
  • Riga 2: importa il modulo integrato path. Questo modulo offre utilità per lavorare con i percorsi di file e directory, inclusa la manipolazione e la normalizzazione dei percorsi.

Passaggio 2: Definizione della funzione getStats

La funzione asincrona getStats accetta come argomento un percorso di file o directory e tenta di recuperare le sue statistiche utilizzando fs.stat.

  • Se ha successo, restituisce le statistiche;
  • In caso di errore, registra un messaggio di errore e restituisce 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;
  }
}
Descrizione del codice
expand arrow
  • Riga 1: dichiara una funzione asincrona chiamata getStats che accetta un parametro filePath;
  • Righe 2, 5: crea un blocco try...catch utilizzato per la gestione degli errori durante l'operazione asincrona;
  • Riga 3: utilizza await fs.stat(filePath) per recuperare informazioni sul file specificato, come dimensione, data di creazione e altri metadati;
  • Riga 4: restituisce l'oggetto stats se l'operazione fs.stat() viene completata con successo;
  • Riga 6: registra un messaggio di errore nella console utilizzando console.error() se l'operazione fallisce;
  • Riga 7: restituisce null per indicare che le statistiche del file non possono essere recuperate.

Passaggio 3: Definizione della funzione analyzeFile

La funzione analyzeFile utilizza la funzione getStats per ottenere le statistiche di un file. Se le statistiche sono disponibili (diverse da null), restituisce un oggetto contenente il nome del file (estratto tramite path.basename) e la sua dimensione.

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

  return {
    name: path.basename(filePath),
    size: stats.size,
  };
}
Descrizione del codice
expand arrow
  • Riga 1: dichiara una funzione asincrona chiamata analyzeFile che accetta un parametro filePath;
  • Riga 2: utilizza await getStats(filePath) per recuperare le statistiche del file per il percorso fornito;
  • Riga 3: verifica se stats è falsy. Se le statistiche non possono essere recuperate, la funzione restituisce null;
  • Righe 5-8: crea e restituisce un oggetto contenente il nome e la dimensione del file. Il nome del file viene estratto tramite path.basename(filePath), mentre la dimensione viene ottenuta da stats.size.

Passaggio 4: Definizione della funzione analyzeDirectory

La funzione analyzeDirectory esegue la scansione di una directory e raccoglie statistiche complete sui suoi contenuti. Funzionamento: legge tutti gli elementi all'interno della directory utilizzando fs.readdir. Per ogni elemento:

  • Costruisce il percorso completo con path.join;
  • Utilizza getStats per rilevare se si tratta di un file o di una cartella;
  • Se è un file:
    • Chiama analyzeFile per ottenere { name, size };
    • Aggiorna i totali, il file più grande e la lista dei file.
  • Se è una directory:
    • Chiama ricorsivamente analyzeDirectory;
    • Unisce i risultati alle statistiche correnti.
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: []
    };
  }
}
Descrizione del codice
expand arrow
  • Riga 1: dichiara una funzione asincrona chiamata analyzeDirectory che accetta un parametro directoryPath;

  • Righe 2-6: inizializza le variabili utilizzate per memorizzare le statistiche della directory, inclusi il totale degli elementi, il totale dei file, la dimensione totale, il file più grande e una lista dei file analizzati;

  • Riga 8: avvia un blocco try per gestire eventuali errori del filesystem;

  • Riga 9: legge il contenuto della directory utilizzando fs.readdir() e memorizza il risultato nell'array items;

  • Riga 11: avvia un ciclo for...of per iterare su ogni elemento della directory;

  • Riga 12: crea il percorso completo per l'elemento corrente utilizzando path.join();

  • Riga 13: recupera le statistiche per l'elemento corrente utilizzando getStats();

  • Riga 14: salta l'elemento corrente se non è stato possibile recuperare le statistiche;

  • Riga 16: incrementa totalItems per ogni file o directory processato con successo;

  • Righe 18-29: gestiscono l'elaborazione dei file:

  • Riga 19: chiama analyzeFile() per recuperare il nome e la dimensione del file;

  • Riga 20: salta il file se l'analisi fallisce;

    • Righe 22-23: aggiornano il conteggio totale dei file e la dimensione totale accumulata;
    • Righe 25-27: aggiornano largestFile se il file corrente è più grande di quello precedentemente registrato;
  • Riga 29: aggiunge le informazioni del file a fileList;

  • Righe 30-42: gestiscono l'elaborazione delle directory:

  • Riga 31: chiama ricorsivamente analyzeDirectory() per la sottodirectory;

    • Righe 33-35: uniscono le statistiche della sottodirectory ai totali correnti;
    • Righe 37-39: aggiornano largestFile se la sottodirectory contiene un file più grande;
  • Riga 41: unisce le liste dei file utilizzando concat();

  • Righe 45-50: restituiscono un oggetto contenente le statistiche finali della directory;

  • Righe 52-62: gestiscono gli errori registrando un messaggio e restituendo un oggetto di statistiche predefinito.

Passaggio 5: Definizione e Invocazione della Funzione main

La funzione main rappresenta il punto di ingresso dello script. Specifica il percorso della directory da analizzare (in questo caso, ./docs), richiama la funzione analyzeDirectory per ottenere le statistiche della directory e dei suoi contenuti, e infine stampa le informazioni raccolte. La funzione visualizza:

  • Numero totale di elementi;
  • Numero totale di file;
  • Dimensione totale;
  • Dettagli sul file più grande;
  • Elenco dei file nella directory.
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();
Descrizione del codice
expand arrow
  • Riga 1: dichiara una funzione asincrona chiamata main;

  • Riga 2: definisce la variabile directoryPath, che memorizza il percorso della directory da analizzare;

  • Riga 3: richiama analyzeDirectory() con il directoryPath specificato e memorizza il risultato nella variabile directoryStats utilizzando await;

  • Righe 5-17: mostrano le statistiche calcolate della directory tramite console.log(), inclusi il numero totale di elementi, file totali, dimensione totale e informazioni sul file più grande;

  • Righe 18-20: iterano sull'array fileList memorizzato in directoryStats;

  • stampano il nome e la dimensione di ciascun file nella directory;

  • Riga 23: richiama la funzione main() per avviare il processo di analisi.

Codice Completo dell'Applicazione

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();
Tutto è chiaro?

Come possiamo migliorarlo?

Grazie per i tuoi commenti!

Sezione 2. Capitolo 10

Chieda ad AI

expand

Chieda ad AI

ChatGPT

Chieda pure quello che desidera o provi una delle domande suggerite per iniziare la nostra conversazione

Sezione 2. Capitolo 10
some-alt