Herramienta de Inspección de Directorios
Desliza para mostrar el menú
Este capítulo te presenta un desafío: crear una aplicación de consola avanzada llamada DirInspect Pro. Esta aplicación te permitirá analizar a fondo cualquier directorio y obtener estadísticas detalladas sobre sus archivos y subdirectorios.
Desafío
Imagina un escenario en el que debes navegar por un laberinto de carpetas que contienen archivos y datos cruciales. DirInspect Pro es tu aliado en este recorrido, proporcionando información integral sobre la estructura y el contenido del directorio.
La aplicación resultante
Prepárate para aprovechar las capacidades de DirInspect Pro. La aplicación te proporcionará información clave, como:
- El número total de elementos;
- El tamaño total de todos los elementos;
- El nombre y tamaño del archivo más grande;
- La lista detallada de nombres y tamaños de archivos individuales.
Dos caminos para elegir
Tienes dos caminos por delante.
- El primero es afrontar este desafío directamente, perfeccionando tus habilidades sin ayuda;
- El segundo es seguir una guía útil que garantiza tu éxito.
Elijas el camino que elijas, te espera una experiencia gratificante que culmina en la creación de una aplicación de consola atractiva y funcional.
Plan maestro
- Paso 1: Importar los módulos requeridos;
- Paso 2: Definir la función getStats;
- Paso 3: Definir la función analyzeFile;
- Paso 4: Definir la función analyzeDirectory;
- Paso 5: Definir e invocar la función main;
- Conclusión;
- Código completo de la aplicación.
Paso 1: Importar los módulos requeridos
Para comenzar esta aventura, necesitas las herramientas adecuadas. Empieza importando dos módulos clave: fs.promises para gestionar el sistema de archivos de forma asíncrona y path para manejar rutas de archivos de manera eficiente.
const fs = require("fs").promises;
const path = require("path");
- Línea 1: importa el módulo incorporado
fs. La propiedad.promisesproporciona acceso a la API basada en promesas, permitiendo realizar operaciones de archivos de forma asíncrona utilizandoasync/await; - Línea 2: importa el módulo incorporado
path. Este módulo ofrece utilidades para trabajar con rutas de archivos y directorios, incluyendo manipulación y normalización de rutas.
Paso 2: Definir la función getStats
La función asíncrona getStats recibe como argumento una ruta de archivo o directorio e intenta obtener sus estadísticas utilizando fs.stat.
- Si tiene éxito, devuelve las estadísticas;
- Si ocurre un error, muestra un mensaje de error y retorna
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;
}
}
- Línea 1: declara una función asíncrona llamada
getStatsque acepta un parámetrofilePath; - Líneas 2, 5: crea un bloque
try...catchutilizado para el manejo de errores durante la operación asíncrona; - Línea 3: utiliza
await fs.stat(filePath)para obtener información sobre el archivo especificado, como su tamaño, fecha de creación y otros metadatos; - Línea 4: retorna el objeto
statssi la operaciónfs.stat()se completa correctamente; - Línea 6: muestra un mensaje de error en la consola usando
console.error()si la operación falla; - Línea 7: retorna
nullpara indicar que no se pudieron obtener las estadísticas del archivo.
Paso 3: Definir la función analyzeFile
La función analyzeFile utiliza la función getStats para obtener las estadísticas de un archivo. Si las estadísticas están disponibles (no son null), retorna un objeto que contiene el nombre del archivo (extraído usando path.basename) y su tamaño.
async function analyzeFile(filePath) {
const stats = await getStats(filePath);
if (!stats) return null;
return {
name: path.basename(filePath),
size: stats.size,
};
}
- Línea 1: declara una función asíncrona llamada
analyzeFileque acepta un parámetrofilePath; - Línea 2: utiliza
await getStats(filePath)para obtener las estadísticas del archivo para la ruta proporcionada; - Línea 3: verifica si
statses falso. Si no se pudieron obtener las estadísticas, la función retornanull; - Líneas 5-8: crea y retorna un objeto que contiene el nombre y el tamaño del archivo. El nombre del archivo se extrae usando
path.basename(filePath), mientras que el tamaño se obtiene destats.size.
Paso 4: Definir la función analyzeDirectory
La función analyzeDirectory escanea un directorio y recopila estadísticas completas sobre su contenido.
Funcionamiento: lee todos los elementos dentro del directorio usando fs.readdir. Para cada elemento:
- Construye la ruta completa con
path.join; - Utiliza
getStatspara detectar si es un archivo o una carpeta; - Si es un archivo:
- Llama a
analyzeFilepara obtener{ name, size }; - Actualiza los totales, el archivo más grande y la lista de archivos.
- Llama a
- Si es un directorio:
- Llama recursivamente a
analyzeDirectory; - Fusiona los resultados en las estadísticas actuales.
- Llama recursivamente a
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: []
};
}
}
-
Línea 1: declara una función asíncrona llamada
analyzeDirectoryque acepta un parámetrodirectoryPath; -
Líneas 2-6: inicializan variables utilizadas para almacenar estadísticas del directorio, incluyendo el total de elementos, total de archivos, tamaño total, el archivo más grande y una lista de archivos analizados;
-
Línea 8: inicia un bloque
trypara manejar posibles errores del sistema de archivos; -
Línea 9: lee el contenido del directorio usando
fs.readdir()y almacena el resultado en el arregloitems; -
Línea 11: inicia un bucle
for...ofpara iterar sobre cada elemento del directorio; -
Línea 12: crea la ruta completa para el elemento actual usando
path.join(); -
Línea 13: obtiene las estadísticas para el elemento actual usando
getStats(); -
Línea 14: omite el elemento actual si no se pudieron obtener sus estadísticas;
-
Línea 16: incrementa
totalItemspor cada archivo o directorio procesado correctamente; -
Líneas 18-29: gestionan el procesamiento de archivos:
-
Línea 19: llama a
analyzeFile()para obtener el nombre y tamaño del archivo; -
Línea 20: omite el archivo si falla el análisis;
- Líneas 22-23: actualizan el conteo total de archivos y el tamaño acumulado;
- Líneas 25-27: actualizan
largestFilesi el archivo actual es más grande que el previamente registrado;
-
Línea 29: agrega la información del archivo a
fileList; -
Líneas 30-42: gestionan el procesamiento de directorios:
-
Línea 31: llama recursivamente a
analyzeDirectory()para el subdirectorio;- Líneas 33-35: fusionan las estadísticas del subdirectorio en los totales actuales;
- Líneas 37-39: actualizan
largestFilesi el subdirectorio contiene un archivo más grande;
-
Línea 41: fusiona las listas de archivos usando
concat(); -
Líneas 45-50: retornan un objeto que contiene las estadísticas finales del directorio;
-
Líneas 52-62: gestionan errores registrando un mensaje y retornando un objeto de estadísticas por defecto.
Paso 5: Definir la función main e invocarla
La función main es el punto de entrada del script. Especifica la ruta del directorio a analizar (en este caso, ./docs), llama a la función analyzeDirectory para obtener las estadísticas del directorio y su contenido, y luego muestra la información recopilada.
La función imprime:
- El número total de elementos;
- El número total de archivos;
- El tamaño total;
- Los detalles sobre el archivo más grande;
- La lista de archivos en el directorio.
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();
-
Línea 1: declara una función asíncrona llamada
main; -
Línea 2: define la variable
directoryPath, que almacena la ruta al directorio que será analizado; -
Línea 3: llama a
analyzeDirectory()con eldirectoryPathespecificado y almacena el resultado en la variabledirectoryStatsusandoawait; -
Líneas 5-17: muestran las estadísticas calculadas del directorio usando
console.log(), incluyendo el número total de elementos, archivos totales, tamaño total e información sobre el archivo más grande; -
Líneas 18-20: recorren el arreglo
fileListalmacenado endirectoryStats; -
registran el nombre y tamaño de cada archivo en el directorio;
-
Línea 23: llama a la función
main()para iniciar el proceso de análisis.
Código completo de la aplicación
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();
¡Gracias por tus comentarios!
Pregunte a AI
Pregunte a AI
Pregunte lo que quiera o pruebe una de las preguntas sugeridas para comenzar nuestra charla