Trabalhar com o sistema de arquivos

Concluído

Cada loja da Tailwind Traders grava os totais de vendas em um arquivo e envia esse arquivo para uma localização central. Para usar esses arquivos, a empresa precisa criar um processo em lotes que possa funcionar com o sistema de arquivos.

Aqui, você aprende a usar o Node.js para ler o sistema de arquivos a fim de descobrir arquivos e diretórios.

Incluir o módulo fs

O Node.js fornece um módulo interno, fs (abreviação em inglês de sistema de arquivos), para trabalhar com o sistema de arquivos. Como ele faz parte do runtime do Node.js, você não precisa instalá-lo, basta fazer referência a ele da mesma forma que faria com qualquer outra dependência.

O módulo fs tem um namespace promises que tem versões promise de todos os métodos. Usar o namespace promise é a maneira preferida de trabalhar com o módulo fs, pois ele permite que você use async para evitar a complexidade dos retornos de chamada ou o bloqueio de métodos síncronos.

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

Você pode usar o módulo fs para realizar várias operações em arquivos e diretórios. Ele tem vários métodos a serem escolhidos. No momento, vamos nos concentrar apenas no que você precisa saber para trabalhar com diretórios.

Listar o conteúdo em um diretório com fs.readdir

Uma das tarefas que você faz com frequência com o módulo fs é listar ou enumerar o conteúdo em um determinado diretório. Por exemplo, a Tailwind Traders tem uma pasta raiz chamada stores. Nessa pasta estão as subpastas organizadas por número da loja. Dentro dessas pastas está o total de arquivos de vendas. A estrutura é parecida com esta:

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

Para ler o conteúdo da pasta, você pode usar o método readdir assíncrono. A maioria das operações no módulo fs tem as opções síncronas (com Sync no final) e assíncronas. Os resultados são retornados em ordem alfanumérica.

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

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

A lista de itens classificados em ordem alfanumérica tem esta aparência:

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

Determinar o tipo de conteúdo com isDirectory

Ao ler o conteúdo de um diretório, você recebe as pastas e os arquivos como uma matriz de cadeias de caracteres. Você pode determinar quais cadeias de caracteres são os arquivos e quais são os diretórios passando a opção withFileTypes. Essa opção retorna uma matriz de objetos Dirent em vez de uma matriz de cadeias de caracteres. O objeto Dirent tem métodos isFile e isDirectory que você pode usar para determinar o tipo de objeto com o qual você está lidando.

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();

A lista de itens classificados em ordem alfanumérica tem esta aparência:

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

Uma observação sobre recursão

Frequentemente, você pode precisar trabalhar com estruturas de diretório complexas que incluem várias pastas aninhadas, cada uma potencialmente contendo mais subpastas e arquivos. Nesses casos, você precisa de uma maneira de navegar por essa estrutura semelhante a uma árvore para encontrar arquivos específicos.

Para conseguir isso, você pode criar uma função que identifica se um item é uma pasta. Se for, a função irá procurar mais arquivos dentro dessa pasta. Esse processo é repetido para cada pasta encontrada.

Isso é feito usando uma técnica chamada de recursão, na qual a função chama a si mesma para pesquisar dentro das pastas recém-encontradas. Isso permite que o programa "percorra" por toda a árvore de diretórios, acessando cada pasta aninhada até que todas as pastas tenham sido exploradas.

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));

A saída se parece com isso:

[
  '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'
]

Usar um ambiente de desenvolvimento predefinido

Este módulo de treinamento oferece um contêiner de desenvolvimento, em um navegador ou em seu computador local. Este contêiner fornece todo o ambiente necessário para que você possa usar este módulo de treinamento sem precisar instalar um IDE ou o Node.js. Você não precisa saber nada sobre o contêiner para concluir este módulo de treinamento.

Verificar seu conhecimento

1.

Qual das operações a seguir você pode realizar com o módulo fs?