Рекурсивное чтение папки в NodeJS

Рекурсивное чтение папки в NodeJS

Рекурсивное чтение папки в NodeJS

Одной из самых частых задач при работе с каталогами (директориями) в NodeJS является их рекурсивное чтение.
Что это такое? Например, у вас есть папка, а в ней еще папка, а в ней еще — и так далее.
И Вам необходимо прочитать содержимое корневой папки и всех дочерних, причем уровень вложенности
может быть сколь угодно произвольным. Для того, чтобы вывести содержимое всех папок как раз и понадобится рекурсия — вызов функцией самой себя.

В примере кода для NodeJS ниже я покажу Вам как этого можно добиться.

Первый пример


/**
 * Принимает функцию вида (err, value) => {}
 * и возвращает ее в виде обещания (промиса).
 */
const { promisify } = require('util');

/**
 * в комментарии к коду ниже есть описание данной функции
 */
const { resolve } = require('path');
const fs = require('fs');
const readdir = promisify(fs.readdir); // промифицирует функцию readdir
const stat = promisify(fs.stat); // тоже самое что и выше, только c stat

/**
 * Рекурсивно обходит папку и возвращает все найденные в ней файлы 
 * в виде одномерного массива абсолютный путей
 * 
 * @param {string} dir Корневая папка
 * @returns {Promise<string[]>} массив строк - путей к файлам
 */
async function getFiles(dir) {

    // асинхронно читает содержимое директории
    const subfolders = await readdir(dir);

    // возвращает список всех путей к файлам
    const files = await Promise.all(subfolders.map(async (subfolder) => {

        // преобразует путь к файлу из относительного в абсолютный
        const res = resolve(dir, subfolder);

        // проверяет директория или файл
        // если директория - рекурсивно вызывает саму себя
        // в противном случае возвращает файл в массив
        return (await stat(res)).isDirectory() ? getFiles(res) : res;
    }));

    // преобразует многомерный полученный массив путей в одномерный
    return files.reduce((a, f) => a.concat(f), []);
}

// запускаем с текущей директорией
getFiles(__dirname)
  .then(files => console.log(files)) // выводим массив путей
  .catch(e => console.error(e)); // или ошибки в консоль

Второй пример:


const { resolve } = require('path');
const { readdir } = require('fs').promises; // промифицированная версия функций из метода

/**
 * 
 * @param {stirng} dir папка, с которой начинается сканирование
 * @returns {Promise<stirng[]>}
 */
async function getFiles(dir) {

    // читаем содержимое директории
    const dirents = await readdir(dir, { withFileTypes: true });

    // как и в прошлом примере проходимся по папкам
    // и, при необходимости рекурсивно вызываем функцию
    const files = await Promise.all(dirents.map((dirent) => {
        const res = resolve(dir, dirent.name);
        return dirent.isDirectory() ? getFiles(res) : res;
    }));

    // преобразуем массив файлов в одномерный
    return Array.prototype.concat(...files);
}

// тестируем
getFiles(__dirname)
    .then(files => console.log(files))
    .catch(err => console.error(err))

Вот таким образом, можно рекурсивно обойти все директории и найти полные пути ко всем файлам
в NodeJS
.

Источник