it-swarm.com.de

Wie erhalten Sie eine Liste der Namen aller Dateien, die sich in einem Verzeichnis in Node.js befinden?

Ich versuche, eine Liste der Namen aller Dateien in einem Verzeichnis zu erhalten, die Node.js verwenden. Ich möchte eine Ausgabe, die ein Array von Dateinamen ist. Wie kann ich das machen?

726
resopollution

Sie können die Methoden fs.readdir oder fs.readdirSync verwenden.

fs.readdir

const testFolder = './tests/';
const fs = require('fs');

fs.readdir(testFolder, (err, files) => {
  files.forEach(file => {
    console.log(file);
  });
});

fs.readdirSync

const testFolder = './tests/';
const fs = require('fs');

fs.readdirSync(testFolder).forEach(file => {
  console.log(file);
});

Der Unterschied zwischen den beiden Methoden besteht darin, dass die erste asynchron ist. Daher müssen Sie eine Callback-Funktion bereitstellen, die ausgeführt wird, wenn der Lesevorgang endet.

Die zweite ist synchron, es wird das Dateinamensfeld zurückgegeben, aber es wird jegliche weitere Ausführung Ihres Codes gestoppt, bis der Lesevorgang abgeschlossen ist.

988
CMS

Die obige Antwort führt jedoch keine rekursive Suche in dem Verzeichnis durch. Folgendes habe ich für eine rekursive Suche gemacht (mit node-walk : npm install walk)

var walk    = require('walk');
var files   = [];

// Walker options
var walker  = walk.walk('./test', { followLinks: false });

walker.on('file', function(root, stat, next) {
    // Add this file to the list of files
    files.Push(root + '/' + stat.name);
    next();
});

walker.on('end', function() {
    console.log(files);
});
172
Ruben Tan

IMO Der bequemste Weg, solche Aufgaben zu erledigen, ist die Verwendung eines glob - Tools. Hier ist ein glob-Paket für node.js. Installieren Sie mit

npm install glob

Verwenden Sie dann Platzhalter, um Dateinamen abzugleichen (Beispiel von der Website des Pakets).

var glob = require("glob")

// options is optional
glob("**/*.js", options, function (er, files) {
  // files is an array of filenames.
  // If the `nonull` option is set, and nothing
  // was found, then files is ["**/*.js"]
  // er is an error object or null.
})
167
KFL

Holen Sie sich Dateien in allen Unterverzeichnissen

function getFiles (dir, files_){
    files_ = files_ || [];
    var files = fs.readdirSync(dir);
    for (var i in files){
        var name = dir + '/' + files[i];
        if (fs.statSync(name).isDirectory()){
            getFiles(name, files_);
        } else {
            files_.Push(name);
        }
    }
    return files_;
}

console.log(getFiles('path/to/dir'))
81
Tito100

Hier ist eine einfache Lösung, die nur die nativen fs- und path-Module verwendet:

// sync version
function walkSync(currentDirPath, callback) {
    var fs = require('fs'),
        path = require('path');
    fs.readdirSync(currentDirPath).forEach(function (name) {
        var filePath = path.join(currentDirPath, name);
        var stat = fs.statSync(filePath);
        if (stat.isFile()) {
            callback(filePath, stat);
        } else if (stat.isDirectory()) {
            walkSync(filePath, callback);
        }
    });
}

oder asynchrone Version (verwendet stattdessen fs.readdir):

// async version with basic error handling
function walk(currentDirPath, callback) {
    var fs = require('fs'),
        path = require('path');
    fs.readdir(currentDirPath, function (err, files) {
        if (err) {
            throw new Error(err);
        }
        files.forEach(function (name) {
            var filePath = path.join(currentDirPath, name);
            var stat = fs.statSync(filePath);
            if (stat.isFile()) {
                callback(filePath, stat);
            } else if (stat.isDirectory()) {
                walk(filePath, callback);
            }
        });
    });
}

Dann rufen Sie einfach an (für die Sync-Version):

walkSync('path/to/root/dir', function(filePath, stat) {
    // do something with "filePath"...
});

oder asynchrone Version:

walk('path/to/root/dir', function(filePath, stat) {
    // do something with "filePath"...
});

Der Unterschied besteht darin, wie der Knoten während der Ausführung der E/A blockiert. Da die oben genannte API die gleiche ist, können Sie einfach die asynchrone Version verwenden, um die maximale Leistung sicherzustellen.

Die Verwendung der synchronen Version bietet jedoch einen Vorteil. Es ist einfacher, etwas Code auszuführen, sobald der Lauf abgeschlossen ist, wie in der nächsten Anweisung nach dem Lauf. Bei der asynchronen Version benötigen Sie eine zusätzliche Möglichkeit, zu wissen, wann Sie fertig sind. Vielleicht erst eine Karte aller Pfade erstellen und diese dann aufzählen. Für einfache Build/Utilities-Skripts (im Gegensatz zu Hochleistungs-Webservern) können Sie die Synchronisierungsversion verwenden, ohne dabei Schäden zu verursachen.

55
Ali

Versprechen mit ES7 verwenden

Asynchrone Verwendung mit mz/fs

Das mz -Modul stellt versprechende Versionen der Kernknotenbibliothek bereit. Sie zu benutzen ist einfach. Installieren Sie zuerst die Bibliothek ...

npm install mz

Dann...

const fs = require('mz/fs');
fs.readdir('./myDir').then(listing => console.log(listing))
  .catch(err => console.error(err));

Alternativ können Sie sie in asynchronen Funktionen in ES7 schreiben:

async function myReaddir () {
  try {
    const file = await fs.readdir('./myDir/');
  }
  catch (err) { console.error( err ) }
};

Update für rekursive Auflistung

Einige Benutzer haben den Wunsch nach einer rekursiven Auflistung angegeben (wenn auch nicht in der Frage) ... Verwenden Sie fs-promise . Es ist eine dünne Hülle um mz .

npm install fs-promise;

dann...

const fs = require('fs-promise');
fs.walk('./myDir').then(
    listing => listing.forEach(file => console.log(file.path))
).catch(err => console.error(err));
22
Evan Carroll

Abhängigkeiten.

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

Definition.

// String -> [String]
function fileList(dir) {
  return fs.readdirSync(dir).reduce(function(list, file) {
    var name = path.join(dir, file);
    var isDir = fs.statSync(name).isDirectory();
    return list.concat(isDir ? fileList(name) : [name]);
  }, []);
}

Verwendungszweck.

var DIR = '/usr/local/bin';

// 1. List all files in DIR
fileList(DIR);
// => ['/usr/local/bin/babel', '/usr/local/bin/bower', ...]

// 2. List all file names in DIR
fileList(DIR).map((file) => file.split(path.sep).slice(-1)[0]);
// => ['babel', 'bower', ...]

Bitte beachten Sie, dass fileList viel zu optimistisch ist. Für etwas Ernsthaftes fügen Sie Fehlerbehandlung hinzu.

15
Hunan Rostomyan

Sie sagen nicht, dass Sie es rekursiv machen möchten, also nehme ich an, Sie brauchen nur direkte Kinder des Verzeichnisses.

Beispielcode:

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

fs.readdirSync('your-directory-path')
  .filter((file) => fs.lstatSync(path.join(folder, file)).isFile());
10
Tyler Long

fs laden:

const fs = require('fs');

Dateien lesen async :

fs.readdir('./dir', function (err, files) {
    // "files" is an Array with files names
});

Dateien lesen sync :

var files = fs.readdirSync('./dir');
7
Eduardo Cuomo

Hier ist eine asynchrone rekursive Version.

    function ( path, callback){
     // the callback gets ( err, files) where files is an array of file names
     if( typeof callback !== 'function' ) return
     var
      result = []
      , files = [ path.replace( /\/\s*$/, '' ) ]
     function traverseFiles (){
      if( files.length ) {
       var name = files.shift()
       fs.stat(name, function( err, stats){
        if( err ){
         if( err.errno == 34 ) traverseFiles()
    // in case there's broken symbolic links or a bad path
    // skip file instead of sending error
         else callback(err)
        }
        else if ( stats.isDirectory() ) fs.readdir( name, function( err, files2 ){
         if( err ) callback(err)
         else {
          files = files2
           .map( function( file ){ return name + '/' + file } )
           .concat( files )
          traverseFiles()
         }
        })
        else{
         result.Push(name)
         traverseFiles()
        }
       })
      }
      else callback( null, result )
     }
     traverseFiles()
    }

Hat die generelle Herangehensweise von @ Hunan-Rostomyan übernommen, etwas knapp gemacht und das Argument excludeDirs hinzugefügt. Es wäre trivial, mit includeDirs zu erweitern, einfach dasselbe Muster:

import * as fs from 'fs';
import * as path from 'path';

function fileList(dir, excludeDirs?) {
    return fs.readdirSync(dir).reduce(function (list, file) {
        const name = path.join(dir, file);
        if (fs.statSync(name).isDirectory()) {
            if (excludeDirs && excludeDirs.length) {
                excludeDirs = excludeDirs.map(d => path.normalize(d));
                const idx = name.indexOf(path.sep);
                const directory = name.slice(0, idx === -1 ? name.length : idx);
                if (excludeDirs.indexOf(directory) !== -1)
                    return list;
            }
            return list.concat(fileList(name, excludeDirs));
        }
        return list.concat([name]);
    }, []);
}

Verwendungsbeispiel:

console.log(fileList('.', ['node_modules', 'typings', 'bower_components']));
3
A T

sorted-Dateinamen abrufen. Sie können Ergebnisse basierend auf einer bestimmten extension filtern, wie '.txt', '.jpg' usw.

import * as fs from 'fs';
import * as Path from 'path';

function getFilenames(path, extension) {
    return fs
        .readdirSync(path)
        .filter(
            item =>
                fs.statSync(Path.join(path, item)).isFile() &&
                (extension === undefined || Path.extname(item) === extension)
        )
        .sort();
}
3
Yas

wenn noch jemand danach sucht, mache ich das:

import fs from 'fs';
import path from 'path';

const getAllFiles = dir =>
    fs.readdirSync(dir).reduce((files, file) => {
        const name = path.join(dir, file);
        const isDirectory = fs.statSync(name).isDirectory();
        return isDirectory ? [...files, ...getAllFiles(name)] : [...files, name];
    }, []);

und seine Arbeit ist sehr gut für mich

1
Josh

Dies ist eine TypeScript-, optional rekursive, optional fehlerprotokollierende und asynchrone Lösung. Sie können einen regulären Ausdruck für die zu suchenden Dateinamen angeben.

Ich habe fs-extra verwendet, weil es eine einfache Verbesserung für fs ist.

import * as FsExtra from 'fs-extra'

/**
 * Finds files in the folder that match filePattern, optionally passing back errors .
 * If folderDepth isn't specified, only the first level is searched. Otherwise anything up
 * to Infinity is supported.
 *
 * @static
 * @param {string} folder The folder to start in.
 * @param {string} [filePattern='.*'] A regular expression of the files you want to find.
 * @param {(Error[] | undefined)} [errors=undefined]
 * @param {number} [folderDepth=0]
 * @returns {Promise<string[]>}
 * @memberof FileHelper
 */
public static async findFiles(
    folder: string,
    filePattern: string = '.*',
    errors: Error[] | undefined = undefined,
    folderDepth: number = 0
): Promise<string[]> {
    const results: string[] = []

    // Get all files from the folder
    let items = await FsExtra.readdir(folder).catch(error => {
        if (errors) {
            errors.Push(error) // Save errors if we wish (e.g. folder perms issues)
        }

        return results
    })

    // Go through to the required depth and no further
    folderDepth = folderDepth - 1

    // Loop through the results, possibly recurse
    for (const item of items) {
        try {
            const fullPath = Path.join(folder, item)

            if (
                FsExtra.statSync(fullPath).isDirectory() &&
                folderDepth > -1)
            ) {
                // Its a folder, recursively get the child folders' files
                results.Push(
                    ...(await FileHelper.findFiles(fullPath, filePattern, errors, folderDepth))
                )
            } else {
                // Filter by the file name pattern, if there is one
                if (filePattern === '.*' || item.search(new RegExp(filePattern, 'i')) > -1) {
                    results.Push(fullPath)
                }
            }
        } catch (error) {
            if (errors) {
                errors.Push(error) // Save errors if we wish
            }
        }
    }

    return results
}
0
Paul F. Wood

Ab Node v10.10.0 ist es möglich, die neue Option withFileTypes für fs.readdir und fs.readdirSync in Kombination mit der Funktion dirent.isDirectory() zu verwenden, um nach Dateinamen in einem Verzeichnis zu filtern. Das sieht so aus:

fs.readdirSync('./dirpath', {withFileTypes: true})
.filter(item => !item.isDirectory())
.map(item => item.name)

Das zurückgegebene Array hat das folgende Format:

['file1.txt', 'file2.txt', 'file3.txt']

Dokumente für die fs.Dirent-Klasse

0
bnp887

Verwenden Sie npmlist-contents module. Es liest den Inhalt und den Unterinhalt des angegebenen Verzeichnisses und gibt die Liste der Pfade von Dateien und Ordnern zurück.

const list = require('list-contents');

list("./dist",(o)=>{
  if(o.error) throw o.error;
   console.log('Folders: ', o.dirs);
   console.log('Files: ', o.files);
});
0
Paweł

Ich habe ein Knotenmodul erstellt, um diese Aufgabe zu automatisieren: mddir

Verwendungszweck

knoten mddir "../relative/path/"

Zur Installation: npm install mddir -g

So erstellen Sie einen Abzug für das aktuelle Verzeichnis: mddir

Für jeden absoluten Pfad generieren: mddir/absolute/path

Für einen relativen Pfad generieren: mddir ~/Documents/was auch immer.

Die md-Datei wird in Ihrem Arbeitsverzeichnis generiert.

Ignoriert derzeit die node_modules- und .git-Ordner.

Fehlerbehebung

Wenn Sie den Fehler "node\r: Keine solche Datei oder ein solches Verzeichnis" erhalten, besteht das Problem, dass Ihr Betriebssystem andere Zeilenenden verwendet und mddir diese nicht analysieren kann, ohne dass Sie den Zeilenendestil explizit auf Unix setzen. Dies betrifft normalerweise Windows, aber auch einige Linux-Versionen. Das Einstellen des Zeilenendes auf den Unix-Stil muss im globalen Ordner "mddir npm" erfolgen.

Zeilenenden fixieren

Npm bin-Ordnerpfad abrufen mit:

npm config get prefix

CD in diesen Ordner

brühen Sie installieren dos2unix

dos2unix lib/node_modules/mddir/src/mddir.js

Dies konvertiert Zeilenenden in Unix anstelle von Dos

Führen Sie dann wie üblich den folgenden Befehl aus: Knoten mddir "../relative/path/".

Beispiel für die generierte Markdown-Dateistruktur 'directoryList.md'

    |-- .bowerrc
    |-- .jshintrc
    |-- .jshintrc2
    |-- Gruntfile.js
    |-- README.md
    |-- bower.json
    |-- karma.conf.js
    |-- package.json
    |-- app
        |-- app.js
        |-- db.js
        |-- directoryList.md
        |-- index.html
        |-- mddir.js
        |-- routing.js
        |-- server.js
        |-- _api
            |-- api.groups.js
            |-- api.posts.js
            |-- api.users.js
            |-- api.widgets.js
        |-- _components
            |-- directives
                |-- directives.module.js
                |-- vendor
                    |-- directive.draganddrop.js
            |-- helpers
                |-- helpers.module.js
                |-- proprietary
                    |-- factory.actionDispatcher.js
            |-- services
                |-- services.cardTemplates.js
                |-- services.cards.js
                |-- services.groups.js
                |-- services.posts.js
                |-- services.users.js
                |-- services.widgets.js
        |-- _mocks
            |-- mocks.groups.js
            |-- mocks.posts.js
            |-- mocks.users.js
            |-- mocks.widgets.js
0
John Byrne

Sie können es auch rekursiv machen.

Dafür gibt es ein NPM-Modul: 

npm dree

Sie können eine Verzeichnisstruktur als Zeichenfolge oder Objekt darstellen. Mit dem File Callback können Sie auch Ihr Ziel erreichen. Wenn Sie möchten, können Sie auch angeben, welche Dateierweiterungen berücksichtigt werden sollen. 

Hier ist der Code:

const dree = require('dree');

const fileNames = [];
const fileCb = function(file) {
    fileNames.Push(file.name);
}

dree.scan('path-to-directory', { extensions: [ 'html', 'js' ] }, fileCb);

console.log(fileNames); // All the html and js files inside the given folder and its subfolders
0
EuberDeveloper

Nur ein Hinweis: Wenn Sie vorhaben, für jede Datei in einem Verzeichnis Operationen auszuführen, versuchen Sie vinyl-fs (wird von gulp verwendet, dem Streaming-Build-System).

Dies funktioniert und speichert das Ergebnis in der Datei test.txt, die sich im selben Verzeichnis befindet

  fs.readdirSync(__dirname).forEach(file => {
    fs.appendFileSync("test.txt", file+"\n", function(err){
    })
})
0
Rama