Exercício – Trabalhar com o sistema de ficheiros

Concluído

A Tailwind Traders tem muitas lojas físicas no mundo inteiro. Todas as noites, estas lojas criam um ficheiro designado por sales.json, que contém o total de todas as respetivas vendas do dia anterior. Esses arquivos são organizados em pastas nomeadas pelo ID da loja.

Neste exercício, você escreve um programa Node.js que pode procurar arquivos chamados sales.json em uma pasta.

Abrir projeto no contêiner de desenvolvimento

  1. Inicie o processo para criar um novo espaço de código GitHub na main ramificação do MicrosoftDocs/node-essentials repositório GitHub.

  2. Na página Criar espaço de código, revise as definições de configuração do espaço de código e selecione Criar novo espaço de código

    Screenshot of the confirmation screen before creating a new codespace.

  3. Aguarde até que o espaço de código inicie. Este processo de arranque pode demorar alguns minutos.

  4. Abra um novo terminal no codespace.

    Gorjeta

    Você pode usar o menu principal para navegar até a opção de menu Terminal e, em seguida, selecionar a opção Novo Terminal.

    Screenshot of the codespaces menu option to open a new terminal.

  5. Valide se o Node.js está instalado em seu ambiente:

    node --version
    

    O contêiner de desenvolvimento usa uma versão Node.js LTS, como v20.5.1. A versão exata pode ser diferente.

  6. Os restantes exercícios deste projeto decorrem no contexto deste contentor de desenvolvimento.

Encontre os ficheiros sales.json

Sua tarefa é encontrar todos os arquivos na pasta stores .

Expanda a pasta stores e cada uma das pastas numeradas no seu interior.

Screenshot that shows the project folder structure.

Inclua o módulo fs

  1. ./nodejs-files Na subpasta, crie um arquivo index.js para abri-lo no editor.

  2. Na parte superior do arquivo, adicione o seguinte código para incluir o módulo fs no arquivo.

    const fs = require("fs").promises;
    
  3. Em seguida, crie a main função que é o ponto de entrada para o seu código. A última linha de código neste arquivo invoca o main método.

    const fs = require("fs").promises;
    
    async function main() {}
    
    main();
    

    Este é o típico código clichê CommonJS para chamar uma função assíncrona.

Escreva uma função para encontrar os sales.json arquivos

  1. Crie uma nova função designada por findSalesFiles que utilize um parâmetro folderName.

    async function findSalesFiles(folderName) {
      // FIND SALES FILES
    }
    
  2. Dentro da findSalesFiles função, adicione o seguinte código para concluir essas tarefas:

    • (1) Adicione uma matriz na parte superior, para manter os caminhos para todos os arquivos de vendas que o programa encontra.
    • (2) Leia o currentFolder com o readdir método.
    • (3) Adicione um bloco para fazer loop em cada item retornado do método usando o readdir loop assíncrono for...of .
    • (4) Adicione uma if instrução para determinar se o item é um arquivo ou um diretório.
    • (5) Se o item for um diretório, chame a função findSalesFiles recursivamente novamente, passando o caminho para o item.
    • (6) Se não for um diretório, adicione uma verificação para garantir que o nome do item corresponda a 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;
    }
    
  3. Chame esta nova função findSaleFiles do método main. Transmita o nome da pasta stores como o local onde procurar os ficheiros.

     async function main() {
       const results = await findSalesFiles("stores");
       console.log(results);
     }
    
  4. O aplicativo completo se parece com:

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

Execute o programa

  1. Digite o seguinte comando no terminal para executar o programa.

    node index.js
    
  2. O programa deve mostrar a seguinte saída.

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

Excelente! Você escreveu com sucesso um programa de linha de comando que pode atravessar qualquer diretório e encontrar todos os arquivos sales.json dentro.

No entanto, a forma como o caminho para as subpastas foi construído neste exemplo é algo ineficiente, porque exige a concatenação de cadeias. Além disso, poderá encontrar problemas noutros sistemas operativos (como o Windows) que utilizam diferentes separadores de caminhos.

Na secção seguinte, irá aprender a construir caminhos que funcionam através dos sistemas operativos ao utilizar o módulo path (caminho).

Está com dificuldades?

Se teve problemas em algum momento deste exercício, eis o código completo. Remova tudo em index.js e substitua por esta solução.

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