Рекурсивный список каталогов с использованием обещаний в узле js - PullRequest
0 голосов
/ 05 сентября 2018

Я хочу рекурсивно перечислить каталоги и читать файлы внутри него, используя обещания в файле node.js. Может кто-нибудь помочь мне преодолеть это?

1 Ответ

0 голосов
/ 05 сентября 2018

Учитывая эту структуру каталогов:

.
├── dirtest
│   ├── bar.txt
│   └── foo
│       └── foo.txt
└── index.js

У вас есть несколько способов сделать это. Давайте рассмотрим наиболее простую верстку с использованием async / await, комментарии в коде:

const fs = require("fs");
const path = require("path");
const util = require("util");

// Promisify the fs functions we will use (or use require("fs").promises)
const astat = util.promisify(fs.stat);
const areaddir = util.promisify(fs.readdir);

/**
 * Get a list of all files in a directory
 * @param {String} dir The directory to inventory
 * @returns {Array} Array of files
 */
async function getFiles(dir) {
  // Get this directory's contents
  const files = await areaddir(dir);
  // Wait on all the files of the directory
  return Promise.all(files
    // Prepend the directory this file belongs to
    .map(f => path.join(dir, f))
    // Iterate the files and see if we need to recurse by type
    .map(async f => {
      // See what type of file this is
      const stats = await astat(f);
      // Recurse if it is a directory, otherwise return the filepath
      return stats.isDirectory() ? getFiles(f) : f;
    }));
}

getFiles(".")
  .then(files => JSON.stringify(files, null, 4))
  .then(console.log)
  .catch(console.error);

Это создаст вложенный массив файлов с добавленными путями:

[
    [
        "dirtest/bar.txt",
        [
            "dirtest/foo/foo.txt"
        ]
    ],
    "index.js"
]

Затем вы можете дополнить это, чтобы получить сплющенный список файлов, нарисовав из этого вопроса: Объединить / сплющить массив массивов в JavaScript? :

/**
 * Flatten an arbitrarrily deep Array of Arrays to a single Array
 * @param {Array} arr Array of Arrays to flatten
 * @returns {Array} The flattened Array
 */
function flatten(arr) {
  return arr.reduce((flat, toFlatten) => flat.concat(Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten), []);
}

/*
 * Same code from above snippet
 */

getFiles(".")
  .then(flatten)
  .then(files => JSON.stringify(files, null, 4))
  .then(console.log)
  .catch(console.error);

Который производит:

[
    "dirtest/bar.txt",
    "dirtest/foo/foo.txt",
    "index.js"
]
...