Получить все каталоги рекурсивно в пределах каталога с помощью nodejs - PullRequest
1 голос
/ 02 октября 2019

Я хочу, чтобы все каталоги синхронизировались в данном каталоге.

<MyFolder>
    |- Folder1
       |- Folder11
       |- Folder12
    |- Folder2
    |- File1.txt
    |- File2.txt
    |- Folder3
        |- Folder31
        |- Folder32

Я ожидал бы получить массив:

["Folder1/Folder11", "Folder1/Folder12", "Folder2", "Folder3/Folder31", "Folder3/Folder32"]

Это мой код:

const fs = require('fs');
const path = require('path');

function flatten(lists) {
  return lists.reduce((a, b) => a.concat(b), []);
}

function getDirectories(srcpath) {
  return fs.readdirSync(srcpath)
  .map(file => path.join(srcpath, file))
  .filter(path => fs.statSync(path).isDirectory());
}

function getDirectoriesRecursive(srcpath) {
  return [srcpath, ...flatten(getDirectories(srcpath).map(getDirectoriesRecursive))];
}

Кто-нибудь поможет мне решить проблему выше?

Ответы [ 2 ]

1 голос
/ 02 октября 2019

async

Вот высоко оптимизированная версия, использующая быстрые * Node fs.Dirent объекты Node. Этот подход позволяет пропустить дорогостоящие вызовы fs.existsSync и fs.statSync на каждом пути -

const { readdir } =
  require ("fs")

const { join } =
  require ("path")

const dirs = async (path = ".") =>
  Promise.all
    ( (await readdir (path, { withFileTypes: true }))
        .map
          ( dirent =>
              dirent .isDirectory ()
                ? dirs (join (path, dirent.name))
                : []
          )
    )
    .then
      ( results =>
          [] .concat (path, ...results)
      )

Вы используете его следующим образом -

dirs ("MyFolder") .then (console.log, console.error)

sync

Мы можем переписать вышеуказанную функцию, используя вместо этого синхронные функции -

const { readdirSync } =
  require ("fs")

const { join } =
  require ("path")

const dirsSync = (path = ".") =>
  [].concat
    ( path
    , ...readdirSync (path, { withFileTypes: true })
        .map
          ( dirent =>
              dirent .isDirectory ()
                ? dirsSync (join (path, dirent.name))
                : []
          )
    )

Вы можете использовать ее следующим образом -

console .log (dirsSync ("MyFolder"))

Это может быть еще более упрощеноиспользуя Array.prototype.flatMap -

const { readdirSync } =
  require ("fs")

const { join } =
  require ("path")

const dirsSync = (path = ".") =>
  [ path
  , ...readdirSync (path, { withFileTypes: true })
      .flatMap
        ( dirent =>
            dirent .isDirectory ()
              ? dirsSync (join (path, dirent.name))
              : []
        )
  ]
0 голосов
/ 02 октября 2019

Вы были почти там, вам просто нужно избегать files (не каталогов), поэтому рекурсия функции getDirectoriesRecursive(srcpath) не выдаст ошибку.

Вот как должен быть финал getDirectoriesRecursive code:

function getDirectoriesRecursive(srcpath) {
  return [srcpath, ...flatten(getDirectories(srcpath).map((p) => {
    try {
      if (fs.existsSync(path)) {
        if (fs.lstatSync(path).isDirectory()) {
          return getDirectoriesRecursive(path);
        }
      }
    } catch (err) {
      console.error(err)
    }
  }).filter(p => p !== undefined))];
}

Это живой рабочий Repl Demo , чтобы показать все каталоги внутри "/opt".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...