programing

디렉터리 nodejs 내의 모든 디렉터리 가져오기

bestprogram 2023. 5. 27. 12:03

디렉터리 nodejs 내의 모든 디렉터리 가져오기

저는 이것이 간단한 일이기를 바랐지만, 저는 그렇게 할 수 있는 어떤 것도 찾을 수 없습니다.

지정된 폴더/디렉토리 내의 모든 폴더/디렉토리를 가져오려고 합니다.

예를 들어 다음과 같습니다.

<MyFolder>
|- SomeFolder
|- SomeOtherFolder
|- SomeFile.txt
|- SomeOtherFile.txt
|- x-directory

다음과 같은 이점이 있을 것으로 예상됩니다.

["SomeFolder", "SomeOtherFolder", "x-directory"]

위의 경로가 그런 식으로 제공되었다면...

위와 같은 작업을 수행할 수 있는 것이 이미 존재합니까?

약속.

import { readdir } from 'fs/promises'

const getDirectories = async source =>
  (await readdir(source, { withFileTypes: true }))
    .filter(dirent => dirent.isDirectory())
    .map(dirent => dirent.name)

콜백

import { readdir } from 'fs'

const getDirectories = (source, callback) =>
  readdir(source, { withFileTypes: true }, (err, files) => {
    if (err) {
      callback(err)
    } else {
      callback(
        files
          .filter(dirent => dirent.isDirectory())
          .map(dirent => dirent.name)
      )
    }
  })

싱크로너스

import { readdirSync } from 'fs'

const getDirectories = source =>
  readdirSync(source, { withFileTypes: true })
    .filter(dirent => dirent.isDirectory())
    .map(dirent => dirent.name)

경로를 사용하여 디렉터리를 나열합니다.

function getDirectories(path) {
  return fs.readdirSync(path).filter(function (file) {
    return fs.statSync(path+'/'+file).isDirectory();
  });
}

재귀해

저는 모든 하위 디렉터리와 모든 하위 디렉터리 등을 가져올 방법을 찾아 여기에 왔습니다.인정된 답변을 바탕으로 저는 다음과 같이 썼습니다.

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

이렇게 하면 됩니다.

CoffeeScript(동기)

fs = require 'fs'

getDirs = (rootDir) ->
    files = fs.readdirSync(rootDir)
    dirs = []

    for file in files
        if file[0] != '.'
            filePath = "#{rootDir}/#{file}"
            stat = fs.statSync(filePath)

            if stat.isDirectory()
                dirs.push(file)

    return dirs

커피스크립트(비동기화)

fs = require 'fs'

getDirs = (rootDir, cb) ->
    fs.readdir rootDir, (err, files) ->
        dirs = []

        for file, index in files
            if file[0] != '.'
                filePath = "#{rootDir}/#{file}"
                fs.stat filePath, (err, stat) ->
                    if stat.isDirectory()
                        dirs.push(file)
                    if files.length == (index + 1)
                        cb(dirs)

JavaScript(비동기화)

var fs = require('fs');
var getDirs = function(rootDir, cb) { 
    fs.readdir(rootDir, function(err, files) { 
        var dirs = []; 
        for (var index = 0; index < files.length; ++index) { 
            var file = files[index]; 
            if (file[0] !== '.') { 
                var filePath = rootDir + '/' + file; 
                fs.stat(filePath, function(err, stat) {
                    if (stat.isDirectory()) { 
                        dirs.push(this.file); 
                    } 
                    if (files.length === (this.index + 1)) { 
                        return cb(dirs); 
                    } 
                }.bind({index: index, file: file})); 
            }
        }
    });
}
 var getDirectories = (rootdir , cb) => {
    fs.readdir(rootdir, (err, files) => {
        if(err) throw err ;
        var dirs = files.map(filename => path.join(rootdir,filename)).filter( pathname => fs.statSync(pathname).isDirectory());
        return cb(dirs);
    })

 }
 getDirectories( myDirectories => console.log(myDirectories));``

라이브러리를 수에는 를 사용할 수 .filehound콜백, 약속 및 동기화 통화를 지원합니다.

약속 사용:

const Filehound = require('filehound');

Filehound.create()
  .path("MyFolder")
  .directory() // only search for directories
  .find()
  .then((subdirectories) => {
    console.log(subdirectories);
  });

콜백 사용:

const Filehound = require('filehound');

Filehound.create()
  .path("MyFolder")
  .directory()
  .find((err, subdirectories) => {
    if (err) return console.error(err);

    console.log(subdirectories);
  });

통화 동기화:

const Filehound = require('filehound');

const subdirectories = Filehound.create()
  .path("MyFolder")
  .directory()
  .findSync();

console.log(subdirectories);

자세한 정보(및 예제)는 다음 문서를 참조하십시오. https://github.com/nspragg/filehound

고지 사항:제가 작가입니다.

node.js 버전 >= v10.13.0의 경우 fs.readdirSync fs 배열을 반환합니다.다른 객체의 경우withFileTypes옵션이 다음으로 설정됨true.

그래서 당신이 사용할 수 있습니다.

const fs = require('fs')

const directories = source => fs.readdirSync(source, {
   withFileTypes: true
}).reduce((a, c) => {
   c.isDirectory() && a.push(c.name)
   return a
}, [])

비동기 호출을 약속하는 fs-extra 및 새 대기 비동기 구문 사용:

const fs = require("fs-extra");

async function getDirectories(path){
    let filesAndDirectories = await fs.readdir(path);

    let directories = [];
    await Promise.all(
        filesAndDirectories.map(name =>{
            return fs.stat(path + name)
            .then(stat =>{
                if(stat.isDirectory()) directories.push(name)
            })
        })
    );
    return directories;
}

let directories = await getDirectories("/")

이 답변은 다음과 같은 차단 기능을 사용하지 않습니다.readdirSync또는statSync외부 의존성을 사용하지 않으며 콜백 지옥의 깊은 곳에서 자신을 찾지 않습니다.

대신에 우리는 약속과 같은 현대적인 자바스크립트 편의를 사용합니다.async-await그리고 순차적으로되지 않고 병렬로 처리됩니다.

const { readdir, stat } =
  require ("fs") .promises

const { join } =
  require ("path")

const dirs = async (path = ".") =>
  (await stat (path)) .isDirectory ()
    ? Promise
        .all
          ( (await readdir (path))
              .map (p => dirs (join (path, p)))
          )
        .then
          ( results =>
              [] .concat (path, ...results)
          )
    : []

샘플 패키지를 설치하고, 우리의 기능을 테스트해 보겠습니다.

$ npm install ramda
$ node

작동하는지 보자꾸나

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

[ '.'
, 'node_modules'
, 'node_modules/ramda'
, 'node_modules/ramda/dist'
, 'node_modules/ramda/es'
, 'node_modules/ramda/es/internal'
, 'node_modules/ramda/src'
, 'node_modules/ramda/src/internal'
]

모듈을 하는 방법은 다음과 같습니다.Parallel우리는 정의를 단순화할 수 있습니다.dirs-

const Parallel =
  require ("./Parallel")

const dirs = async (path = ".") =>
  (await stat (path)) .isDirectory ()
    ? Parallel (readdir (path))
        .flatMap (f => dirs (join (path, f)))
        .then (results => [ path, ...results ])
    : []

Parallel위에 사용된 모듈은 유사한 문제를 해결하기 위해 설계된 함수 집합에서 추출된 패턴이었습니다.자세한 내용은 이와 관련된 Q&A를 참조하십시오.

또한 비동기 버전의 getDirectories에서는 다음을 위해 비동기 모듈이 필요합니다.

var fs = require('fs');
var path = require('path');
var async = require('async'); // https://github.com/caolan/async

// Original function
function getDirsSync(srcpath) {
  return fs.readdirSync(srcpath).filter(function(file) {
    return fs.statSync(path.join(srcpath, file)).isDirectory();
  });
}

function getDirs(srcpath, cb) {
  fs.readdir(srcpath, function (err, files) {
    if(err) { 
      console.error(err);
      return cb([]);
    }
    var iterator = function (file, cb)  {
      fs.stat(path.join(srcpath, file), function (err, stats) {
        if(err) { 
          console.error(err);
          return cb(false);
        }
        cb(stats.isDirectory());
      })
    }
    async.filter(files, iterator, cb);
  });
}

ES6가 포함된 완전 비동기 버전으로 네이티브 패키지, fs.promise 및 async/wait만 파일 작업을 병렬로 수행합니다.

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

async function listDirectories(rootPath) {
    const fileNames = await fs.promises.readdir(rootPath);
    const filePaths = fileNames.map(fileName => path.join(rootPath, fileName));
    const filePathsAndIsDirectoryFlagsPromises = filePaths.map(async filePath => ({path: filePath, isDirectory: (await fs.promises.stat(filePath)).isDirectory()}))
    const filePathsAndIsDirectoryFlags = await Promise.all(filePathsAndIsDirectoryFlagsPromises);
    return filePathsAndIsDirectoryFlags.filter(filePathAndIsDirectoryFlag => filePathAndIsDirectoryFlag.isDirectory)
        .map(filePathAndIsDirectoryFlag => filePathAndIsDirectoryFlag.path);
}

테스트 완료, 작동이 양호합니다.

graph-fs를 사용할 수 있습니다.

const {Node} = require("graph-fs");
const directory = new Node("/path/to/directory");

const subDirectories = directory.children.filter(child => child.is.directory);

답변의 CoffeeScript 버전(적절한 오류 처리 포함):

fs = require "fs"
{join} = require "path"
async = require "async"

get_subdirs = (root, callback)->
    fs.readdir root, (err, files)->
        return callback err if err
        subdirs = []
        async.each files,
            (file, callback)->
                fs.stat join(root, file), (err, stats)->
                    return callback err if err
                    subdirs.push file if stats.isDirectory()
                    callback null
            (err)->
                return callback err if err
                callback null, subdirs

비동기에 따라 다름

또는 모듈을 사용합니다! (모든 것을 위한 모듈이 있습니다.)[긴급 필요]

모두 사용해야 하는 경우async판본이런 거 있으면 돼요.

  1. 디렉터리 길이를 기록하고 모든 비동기 상태 작업이 완료되었는지 여부를 나타내는 표시기로 사용합니다.

  2. 비동기 상태 작업이 완료되면 모든 파일 상태가 확인되었으므로 콜백을 호출합니다.

Node.js가 단일 스레드인 경우에만 작동합니다. 두 비동기 작업이 동시에 카운터를 증가시키지 않는다고 가정하기 때문입니다.

'use strict';

var fs = require("fs");
var path = require("path");
var basePath = "./";

function result_callback(results) {
    results.forEach((obj) => {
        console.log("isFile: " + obj.fileName);
        console.log("fileName: " + obj.isFile);
    });
};

fs.readdir(basePath, (err, files) => {
    var results = [];
    var total = files.length;
    var finished = 0;

    files.forEach((fileName) => {
        // console.log(fileName);
        var fullPath = path.join(basePath, fileName);

        fs.stat(fullPath, (err, stat) => {
            // this will work because Node.js is single thread
            // therefore, the counter will not increment at the same time by two callback
            finished++;

            if (stat.isFile()) {
                results.push({
                    fileName: fileName,
                    isFile: stat.isFile()
                });
            }

            if (finished == total) {
                result_callback(results);
            }
        });
    });
});

보시다시피, 이것은 "깊이 우선" 접근법이고, 이것은 콜백 지옥을 초래할 수 있고, 그것은 꽤 "기능적"이지 않습니다. 사람들은 비동기 작업을 Promise 개체로 포장함으로써 Promise로 이 문제를 해결하려고 합니다.

'use strict';

var fs = require("fs");
var path = require("path");
var basePath = "./";

function result_callback(results) {
    results.forEach((obj) => {
        console.log("isFile: " + obj.fileName);
        console.log("fileName: " + obj.isFile);
    });
};

fs.readdir(basePath, (err, files) => {
    var results = [];
    var total = files.length;
    var finished = 0;

    var promises = files.map((fileName) => {
        // console.log(fileName);
        var fullPath = path.join(basePath, fileName);

        return new Promise((resolve, reject) => {
            // try to replace fullPath wil "aaa", it will reject
            fs.stat(fullPath, (err, stat) => {
                if (err) {
                    reject(err);
                    return;
                }

                var obj = {
                    fileName: fileName,
                    isFile: stat.isFile()
                };

                resolve(obj);
            });
        });
    });

    Promise.all(promises).then((values) => {
        console.log("All the promise resolved");
        console.log(values);
        console.log("Filter out folder: ");
        values
            .filter((obj) => obj.isFile)
            .forEach((obj) => {
                console.log(obj.fileName);
            });
    }, (reason) => {
        console.log("Not all the promise resolved");
        console.log(reason);
    });
});

use fs、path 모듈이 폴더를 가져올 수 있습니다.Promise를 사용합니다.를 채울 경우 디렉토리()isFile() Nodejs--fs--fs로 변경할 수 있습니다.Stats.마지막으로 Nodejs---Path에서 파일 'name file'extname 등을 가져올 수 있습니다.

var fs = require("fs"),
path = require("path");
//your <MyFolder> path
var p = "MyFolder"
fs.readdir(p, function (err, files) {
    if (err) {
        throw err;
    }
    //this can get all folder and file under  <MyFolder>
    files.map(function (file) {
        //return file or folder path, such as **MyFolder/SomeFile.txt**
        return path.join(p, file);
    }).filter(function (file) {
        //use sync judge method. The file will add next files array if the file is directory, or not. 
        return fs.statSync(file).isDirectory();
    }).forEach(function (files) {
        //The files is array, so each. files is the folder name. can handle the folder.
        console.log("%s", files);
    });
});

글로벌 패키지를 사용하여 디렉터리만 찾으려면 슬래시를 추가하십시오.

import {promise as glob} from "glob-promise"

const firstLevelFolders = await glob("MyFolder/*/")
const recursiveFolders = await glob("MyFolder/**/")

다른 누군가가 웹 검색에서 여기까지 와서 이미 종속성 목록에 그룬트를 가지고 있는 경우, 이에 대한 대답은 사소한 것이 됩니다.제 솔루션은 다음과 같습니다.

/**
 * Return all the subfolders of this path
 * @param {String} parentFolderPath - valid folder path
 * @param {String} glob ['/*'] - optional glob so you can do recursive if you want
 * @returns {String[]} subfolder paths
 */
getSubfolders = (parentFolderPath, glob = '/*') => {
    return grunt.file.expand({filter: 'isDirectory'}, parentFolderPath + glob);
}

또 다른 재귀적 접근법

마유르가 나를 알게 해준 것에 감사합니다.withFileTypes특정 폴더의 파일을 재귀적으로 가져오기 위해 다음 코드를 작성했습니다.디렉터리만 가져오도록 쉽게 수정할 수 있습니다.

const getFiles = (dir, base = '') => readdirSync(dir, {withFileTypes: true}).reduce((files, file) => {
    const filePath = path.join(dir, file.name)
    const relativePath = path.join(base, file.name)
    if(file.isDirectory()) {
        return files.concat(getFiles(filePath, relativePath))
    } else if(file.isFile()) {
        file.__fullPath = filePath
        file.__relateivePath = relativePath
        return files.concat(file)
    }
}, [])

함수형 프로그래밍

const fs = require('fs')
const path = require('path')
const R = require('ramda')

const getDirectories = pathName => {
    const isDirectory = pathName => fs.lstatSync(pathName).isDirectory()
    const mapDirectories = pathName => R.map(name => path.join(pathName, name), fs.readdirSync(pathName))
    const filterDirectories = listPaths => R.filter(isDirectory, listPaths)

    return {
        paths:R.pipe(mapDirectories)(pathName),
        pathsFiltered: R.pipe(mapDirectories, filterDirectories)(pathName)
    }
}

모듈을 사용하는 것이 합리적이라면 dree를 사용할 수 있습니다.

const dree = require('dree');

const options = {
  depth: 1
};
const fileCallback = function() {};

const directories = [];
const dirCallback = function(dir) {
 directories.push(dir.name);
};

dree.scan('./dir', {});

console.log(directories);

지정된 경로(./dir")의 하위 디렉터리가 인쇄됩니다.

옵션을 지정하지 않은 경우depth: 1지정된 경로의 지시된 하위 디렉터리뿐만 아니라 모든 디렉터리를 재귀적인 방식으로 가져올 수도 있습니다.

언급URL : https://stackoverflow.com/questions/18112204/get-all-directories-within-directory-nodejs