Trabajo con el sistema de archivos

Completado

En Tailwind Traders, cada una de sus tiendas escribe sus totales de ventas en un archivo y ese archivo se envía a una ubicación central. Para usar esos archivos, la compañía debe crear un proceso por lotes que pueda funcionar con el sistema de archivos.

Aquí obtendrá información sobre cómo usar Node.js para leer el sistema de archivos con el propósito de descubrir archivos y directorios.

Inclusión del módulo fs

Node.js proporciona un módulo integrado, fs (abreviatura de file system), para trabajar con el sistema de archivos. Dado que forma parte del entorno de ejecución de Node.js, no es necesario instalarlo; solo úselo como referencia como con cualquier otra dependencia.

El módulo fs tiene un espacio de nombres promises que tiene versiones promise de todos los métodos. El uso del espacio de nombres promise es la manera preferida de trabajar con el módulo fs, ya que le permite usar async para evitar el desorden de las devoluciones de llamada o el bloqueo de métodos sincrónicos.

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

Puede usar el módulo fs para realizar varias operaciones en archivos y directorios. Tiene varios métodos entre los que elegir. Por el momento, nos centraremos únicamente en lo que necesitamos saber para trabajar con directorios.

Muestra del contenido en un directorio con fs.readdir

Una de las tareas que se harán bastante a menudo con el módulo fs es mostrar o enumerar el contenido en un directorio. Por ejemplo, Tailwind Traders tiene una carpeta raíz denominada stores. En esa carpeta hay subcarpetas organizadas por número de tienda. Dentro de esas carpetas están los archivos de totales de ventas. El aspecto de esta estructura es el siguiente:

📂 stores
    📄 sales.json
    📄 totals.txt
    📂 201
    📂 202

Para leer el contenido de la carpeta, se puede usar el método readdir. La mayoría de las operaciones del módulo fs tienen opciones sincrónicas (seguidas de Sync) y asincrónicas. Los resultados se devuelven en orden alfanumérico.

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

async function main() {
    const items = await fs.readdir("stores");
    console.log(items);
}
main();

La lista ordenada alfanumérica de elementos tiene este aspecto:

[ '201', '202', '203', '204' ]

Determinación del tipo de contenido con isDirectory

Cuando se lee el contenido de un directorio, se obtienen las carpetas y los archivos como una matriz de cadenas. Para distinguir cuáles son archivos y cuáles directorios, se puede pasar la opción withFileTypes. Esta opción devuelve una matriz de objetos Dirent, en lugar de una matriz de cadenas. El objeto Dirent tiene los métodos isFile y isDirectory, que se pueden usar para determinar con qué tipo de objeto estamos tratando.

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

async function main() {
    const items = await fs.readdir("stores", { withFileTypes: true });
    for (let item of items) {
        const type = item.isDirectory() ? "folder" : "file";
        console.log(`${item.name}: ${type}`);
    }
}
main();

La lista ordenada alfanumérica de elementos tiene este aspecto:

201: folder
202: folder
203: folder
204: folder

Un apunte sobre recursividad

A menudo, es posible que deba trabajar con estructuras de directorio complejas que incluyen varias carpetas anidadas, cada una de las cuales puede contener más subcarpetas y archivos. En tales casos, necesita una manera de navegar por esta estructura similar a un árbol para buscar archivos específicos.

Para ello, puede crear una función que identifique si un elemento es una carpeta. Si es así, la función busca más archivos dentro de esa carpeta. Este proceso se repite para cada carpeta que se encuentra.

Esto se logra mediante una técnica denominada recursividad, donde la función se llama a sí misma para buscar dentro de las carpetas recién encontradas. Esto permite que el programa "recorra" todo el árbol de directorios, llegando a cada carpeta anidada hasta que se hayan explorado todas las carpetas.

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

async function findFiles(folderName) {

    let results = []

    results.push(`${folderName}`);

    const items = await fs.readdir(folderName, { withFileTypes: true });

    for (const item of items) {
        if (item.isDirectory()) {

            // RECURSION - calling the function from within itself
            const resultsReturned = await findFiles(`${folderName}/${item.name}`);
            results = results.concat(resultsReturned);
        } else {
            results.push(`${folderName}/${item.name}`);
        }
    }

    return results;
}

findFiles("stores").then((results) => console.log(results));

El resultado tendrá una apariencia similar a la siguiente:

[
  'stores',
  'stores/201',
  'stores/201/sales.json',
  'stores/202',
  'stores/202/sales.json',
  'stores/203',
  'stores/203/sales.json',
  'stores/204',
  'stores/204/sales.json'
]

Uso de un entorno de desarrollo predefinido

Este módulo de entrenamiento ofrece un contenedor de desarrollo, ya sea en un explorador o en el equipo local. Este contenedor proporciona todo el entorno necesario para que pueda usar este módulo de entrenamiento sin tener que instalar un IDE o Node.js. No es necesario saber nada sobre el contenedor para completar este módulo de entrenamiento.

Comprobación de conocimientos

1.

¿Cuál de las operaciones siguientes se puede realizar con el módulo fs?