Ejercicio: Trabajar con el sistema de archivos
Tailwind Traders tiene muchas tiendas físicas repartidas por todo el mundo. Cada noche, las tiendas crean un archivo denominado sales.json que contiene el total de todas las ventas del día anterior. Estos archivos se organizan en carpetas nombradas por id. de tienda.
En este ejercicio, va a escribir un programa de Node.js que busca archivos llamados sales.json en una carpeta.
Abrir el proyecto en el contenedor de desarrollo
Inicie el proceso para crear una nueva instancia de GitHub Codespace en la rama
main
del repositorio de GitHubMicrosoftDocs/node-essentials
.En la página Crear codespace, revise las opciones de configuración de codespace y, después, seleccione Crear nuevo codespace
Espere a que se inicie Codespace. Este proceso de startup puede tardar unos minutos.
Abra un nuevo terminal en el codespace.
Compruebe que Node.js está instalado en el entorno:
node --version
El contenedor de desarrollo usa una versión Node.js LTS, como
v20.5.1
. La versión exacta podría ser diferente.Los demás ejercicios de este proyecto tienen lugar en el contexto de este contenedor de desarrollo.
Búsqueda de los archivos sales.json
La tarea es buscar todos los archivos de la carpeta stores.
Expanda la carpeta stores y cada una de las carpetas numeradas en su interior.
Inclusión del módulo fs
En la subcarpeta
./nodejs-files
, cree un archivo index.js para abrirlo en el editor.En la parte superior del archivo, agregue el código siguiente para incluir el módulo fs en el archivo.
const fs = require("fs").promises;
A continuación, cree la función
main
, que es el punto de entrada del código. La última línea de código de este archivo invoca al métodomain
.const fs = require("fs").promises; async function main() {} main();
Este es el código reutilizable de CommonJS típico para llamar a una función asincrónica.
Escribir una función para buscar los archivos sales.json
Cree una función denominada
findSalesFiles
que tome un parámetrofolderName
.async function findSalesFiles(folderName) { // FIND SALES FILES }
Dentro de la función
findSalesFiles
, agregue el código siguiente para completar estas tareas:- (1) Agregue una matriz al inicio que contenga las rutas de acceso a todos los archivos de ventas que encuentre el programa.
- (2) Lea currentFolder con el método
readdir
. - (3) Agregue un bloque para recorrer en bucle cada elemento devuelto desde el método
readdir
mediante el bucle asincrónicofor...of
. - (4) Agregue una instrucción
if
para saber si el elemento es un archivo o un directorio. - (5) Si el elemento es un directorio, llame recursivamente a la función
findSalesFiles
de nuevo, pasando la ruta de acceso al elemento. - (6) Si no lo es, agregue una comprobación para asegurarse de que el nombre del elemento coincide con sales.json.
async function findSalesFiles(folderName) { // (1) Add an array at the top, to hold the paths to all the sales files that the program finds. let results = []; // (2) Read the currentFolder with the `readdir` method. const items = await fs.readdir(folderName, { withFileTypes: true }); // (3) Add a block to loop over each item returned from the `readdir` method using the asynchronous `for...of` loop. for (const item of items) { // (4) Add an `if` statement to determine if the item is a file or a directory. if (item.isDirectory()) { // (5) If the item is a directory, recursively call the function `findSalesFiles` again, passing in the path to the item. const resultsReturned = await findSalesFiles(`${folderName}/${item.name}`); results = results.concat(resultsReturned); } else { // (6) If it's not a directory, add a check to make sure the item name matches *sales.json*. if (item.name === "sales.json") { results.push(`${folderName}/${item.name}`); } } } return results; }
Llame a esta función nueva de
findSaleFiles
desde el métodomain
. Pase el nombre de la carpeta stores como la ubicación en la que buscar archivos.async function main() { const results = await findSalesFiles("stores"); console.log(results); }
La aplicación completa tiene el siguiente aspecto:
const fs = require("fs").promises; async function findSalesFiles(folderName) { // (1) Add an array at the top, to hold the paths to all the sales files that the program finds. let results = []; // (2) Read the currentFolder with the `readdir` method. const items = await fs.readdir(folderName, { withFileTypes: true }); // (3) Add a block to loop over each item returned from the `readdir` method using the asynchronous `for...of` loop. for (const item of items) { // (4) Add an `if` statement to determine if the item is a file or a directory. if (item.isDirectory()) { // (5) If the item is a directory, recursively call the function `findSalesFiles` again, passing in the path to the item. const resultsReturned = await findSalesFiles(`${folderName}/${item.name}`); results = results.concat(resultsReturned); } else { // (6) If it's not a directory, add a check to make sure the item name matches *sales.json*. if (item.name === "sales.json") { results.push(`${folderName}/${item.name}`); } } } return results; } async function main() { const results = await findSalesFiles("stores"); console.log(results); } main();
Ejecutar el programa
Escriba el siguiente comando en el terminal para ejecutar el programa.
node index.js
El programa debe mostrar la salida siguiente.
[ 'stores/201/sales.json', 'stores/202/sales.json', 'stores/203/sales.json', 'stores/204/sales.json', ]
Excelente. Ha escrito correctamente un programa de línea de comandos que puede recorrer cualquier directorio y encontrar todos los archivos sales.json que haya en ellos.
A pesar de ello, el modo en que se ha construido la ruta de acceso a las subcarpetas en este ejemplo es un poco engorroso, porque requiere concatenar cadenas. Además, es posible que surjan incidencias en otros sistemas operativos (como Windows) que usan separadores de ruta de acceso diferentes.
En la sección siguiente, obtendremos información sobre cómo construir rutas de acceso que funcionen en varios sistemas operativos mediante el módulo path.
¿Se ha bloqueado?
Si se ha bloqueado en algún momento de este ejercicio, aquí tiene el código completo. Quite todo en index.js y reemplácelo por esta solución.
const fs = require("fs").promises;
async function findSalesFiles(folderName) {
// (1) Add an array at the top, to hold the paths to all the sales files that the program finds.
let results = [];
// (2) Read the currentFolder with the `readdir` method.
const items = await fs.readdir(folderName, { withFileTypes: true });
// (3) Add a block to loop over each item returned from the `readdir` method using the asynchronous `for...of` loop.
for (const item of items) {
// (4) Add an `if` statement to determine if the item is a file or a directory.
if (item.isDirectory()) {
// (5) If the item is a directory, recursively call the function `findSalesFiles` again, passing in the path to the item.
const resultsReturned = await findSalesFiles(`${folderName}/${item.name}`);
results = results.concat(resultsReturned);
} else {
// (6) If it's not a directory, add a check to make sure the item name matches *sales.json*.
if (item.name === "sales.json") {
results.push(`${folderName}/${item.name}`);
}
}
}
return results;
}
async function main() {
const results = await findSalesFiles("stores");
console.log(results);
}
main();