it-swarm.com.de

Liefert alle Verzeichnisse im Verzeichnis nodejs

Ich hatte gehofft, dass dies eine einfache Sache sein würde, aber ich finde nichts dazu.

Ich möchte nur alle Ordner/Verzeichnisse in einem bestimmten Ordner/Verzeichnis abrufen.

Also zum Beispiel:

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

Ich würde erwarten, eine Reihe von:

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

Oder das oben mit dem Pfad, wenn es so war, wie es serviert wurde ...

Gibt es also schon etwas, um dies zu tun?

192
Grofit

Hier ist eine kürzere, synchrone Version von diese Antwort , die alle Verzeichnisse (versteckt oder nicht) im aktuellen Verzeichnis auflisten kann:

const { lstatSync, readdirSync } = require('fs')
const { join } = require('path')

const isDirectory = source => lstatSync(source).isDirectory()
const getDirectories = source =>
  readdirSync(source).map(name => join(source, name)).filter(isDirectory)
347
Nick McCurdy

Dank der JavaScript ES6 (ES2015) -Syntaxfunktionen ist es ein einziger Liner:

** Synchronversion **

const { readdirSync, statSync } = require('fs')
const { join } = require('path')

const dirs = p => readdirSync(p).filter(f => statSync(join(p, f)).isDirectory())

Asynchrone Version für Node.js 10+ (experimentell)

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

const dirs = async path => {
  let dirs = []
  for (const file of await readdir(path)) {
    if ((await stat(join(path, file))).isDirectory()) {
      dirs = [...dirs, file]
    }
  }
  return dirs
}
80
pravdomil

Verzeichnisse nach einem Pfad auflisten.

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

Rekursive Lösung

Ich kam hierher auf der Suche nach einer Möglichkeit, alle Unterverzeichnisse und alle ihre Unterverzeichnisse usw. zu erhalten. Aufbauend auf der akzeptierten Antwort schrieb ich Folgendes:

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

Das sollte es tun:

CoffeeScript (Sync)

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

CoffeeScript (async)

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

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})); 
            }
        }
    });
}
9
nicksweet

Wenn Sie externe Bibliotheken verwenden können, können Sie alternativ filehound verwenden. Es unterstützt Rückrufe, Versprechen und Synchronisierungsaufrufe. 

Versprechungen verwenden:

const Filehound = require('filehound');

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

Rückrufe verwenden:

const Filehound = require('filehound');

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

    console.log(subdirectories);
  });

Sync-Aufruf:

const Filehound = require('filehound');

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

console.log(subdirectories);

Weitere Informationen (und Beispiele) finden Sie in den Dokumenten: https://github.com/nspragg/filehound

Haftungsausschluss: Ich bin der Autor.

5
nickool

Verwenden von fs-extra, was die async fs-Aufrufe und die neue async-Syntax von waitit verspricht: 

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("/")
3
1mike12

Bei node.js version> = v10.13.0 gibt fs.readdirSync ein Array von fs.Dirent objects zurück, wenn die Option withFileTypes auf true gesetzt ist.

So können Sie verwenden,

const fs = require('fs')

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

Und eine Async-Version von getDirectories benötigen Sie das async-Modul dafür:

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);
  });
}
3
JumpLink
 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));``
2

Diese Antwort verwendet keine blockierenden Funktionen wie readdirSync oder statSync. Es verwendet keine externen Abhängigkeiten und befindet sich nicht in den Tiefen der Callback-Hölle.

Stattdessen verwenden wir moderne JavaScript-Bequemlichkeiten wie Promises und und async-await-Syntaxen. Und asynchrone Ergebnisse werden parallel verarbeitet. nicht sequentiell -

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)
          )
    : []

Ich werde ein Beispielpaket installieren und dann unsere Funktion testen -

$ npm install ramda
$ node

Mal sehen, wie es funktioniert -

> 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'
]

Mit einem verallgemeinerten Modul, Parallel, können wir die Definition von dirs vereinfachen.

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 ])
    : []

Das oben verwendete Modul Parallel war ein Muster, das aus einer Reihe von Funktionen extrahiert wurde, die zur Lösung eines ähnlichen Problems entwickelt wurden. Weitere Erklärungen finden Sie in dieser bezogenen F & A .

1
user633183

Wenn Sie alle async-Version verwenden müssen. Sie können so etwas haben.

  1. Zeichnen Sie die Verzeichnislänge auf und verwenden Sie sie als Indikator, um festzustellen, ob alle asynchronen Stat-Tasks abgeschlossen sind.

  2. Wenn die asynchronen Stat-Tasks abgeschlossen sind, wurde der gesamte Dateistatus geprüft. Rufen Sie also den Rückruf auf

Dies funktioniert nur, solange Node.js Single-Thread ist, da davon ausgegangen wird, dass keine zwei asynchronen Tasks gleichzeitig den Zähler erhöhen.

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

Wie Sie sehen können, handelt es sich hierbei um einen "Deep First" -Ansatz, der zur Rückruf-Hölle führen kann und nicht ganz "funktional" ist. Leute versuchen, dieses Problem mit Promise zu lösen, indem sie die asynchrone Aufgabe in ein Promise-Objekt verpacken.

'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);
    });
});
1
code4j

benutze fs 、 path Modul kann den Ordner bekommen. dieses Versprechen verwenden. Wenn Sie die Füllung erhalten, können Sie isDirectory () in isFile ()Nodejs - fs - fs.Stats ändern. Zum Schluss erhalten Sie die Datei Dateiname 'extname und so weiter Nodejs --- Pfad

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);
    });
});
1
Howard

CoffeeScript-Version von diese Antwort , mit korrekter Fehlerbehandlung:

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

Abhängig von async

Alternativ dazu verwenden Sie dazu ein Modul! (Es gibt Module für alles. [Zitat benötigt])

1
1j01

Voll asynchrone Version mit ES6, nur native Pakete, fs.promises und async/await, führen Dateioperationen parallel aus:

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

Getestet funktioniert es gut.

0

Ein weiterer rekursiver Ansatz

Vielen Dank an Mayur für das Kennenlernen von withFileTypes. Ich habe folgenden Code geschrieben, um Dateien eines bestimmten Ordners rekursiv abzurufen. Es kann leicht modifiziert werden, um nur Verzeichnisse zu erhalten.

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)
    }
}, [])
0

Nur wenn jemand anderes von einer Websuche hierher kommt und Grunt bereits in seiner Abhängigkeitsliste steht, wird die Antwort auf diese Frage trivial. Hier ist meine Lösung:

/**
 * 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);
}
0
Artif3x

Ich würde persönlich die stat-Funktion außerhalb der Schleife erklären - etwa so:

function getSubDirs(dir, cb) {
    fs.readdir(dir, function(err, files) {
        var dirs = [],
        filePath,
        checkDirectory = function(err, stat) {
            if(stat.isDirectory()) {
                dirs.Push(files[i]);
            }
            if(i + 1 === l) { // last record
                cb(dirs);
            }
        };

        for(var i=0, l=files.length; i<l; i++) {
            if(files[i][0] !== '.') { // ignore hidden
                filePath = dir+'/'+files[i];
                fs.stat(filePath, checkDirectory);
            }
        }
    });
}

JShint beschwert sich anderweitig und möglicherweise erstellen Sie einen neuen Funktionsaufruf in jedem Schleifendurchlauf.

0
derekdreery

Async/Erwartungsvariante:

async function getFolders(path) {
    let result = Array();
    let files = await fs.readdir(path);
    for (let i = 0; i < files.length; i++) {
        var filePath = path + '/' + file;
        if (await fs.stat(filePath).isDirectory()) {
            result.Push(filePath);
        }
    }

    return result;
}

Ich empfehle auch die Verwendung von fs-extra anstelle von fs ..

0
jabko87

funktionale Programmierung

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)
    }
}
0
Roy Alcala