Frage

Ich versuche, eine Liste mit den Namen aller Dateien in einem Verzeichnis zu erhalten mit Node.js. Ich mag Ausgabe, die ein Array von Dateinamen ist. Wie kann ich das tun?

War es hilfreich?

Lösung

Sie können über den fs.readdir oder fs.readdirSync Methoden.

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, so dass Sie eine Callback-Funktion zur Verfügung zu stellen, die bei dem Lesevorgang enden ausgeführt werden.

Die zweite synchron ist, wird es die Dateinamen Array zurückgeben, aber es wird eine weitere Ausführung des Codes, bis der Lesevorgang endet zu stoppen.

Andere Tipps

IMO die meisten convinient Weg, um solche Aufgaben zu tun, ist ein glob Tool zu verwenden. Hier ist ein glob Paket für node.js. Installieren Sie mit

npm install glob

Dann Platzhalter verwenden, um Dateinamen (zB aus dem Paket der Website genommen) zu entsprechen

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

Die Antwort oben nicht eine rekursive Suche in dem Verzeichnis, obwohl auszuführen. Hier ist, was ich für eine rekursive Suche hat (unter Verwendung von Knoten-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);
});

Get-Dateien in allen subdirs

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

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

// 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 Asynchron-Version (verwendet fs.readdir statt):

// 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 (für Sync-Version):

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

oder Asynchron-Version:

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

Der Unterschied liegt darin, wie Knoten blockiert, während die IO ausführt. Da die API über das gleiche ist, Sie könnten nur von der Asynchron-Version verwenden, um maximale Leistung zu gewährleisten.

Allerdings gibt es einen Vorteil, um die synchrone Version. Es ist einfacher, einen Code auszuführen, sobald der Fuß gemacht wird, wie in der nächsten Anweisung nach der Wanderung. Mit der Asynchron-Version, müßten Sie einige zusätzliche Möglichkeit zu wissen, wenn Sie fertig sind. Vielleicht eine Karte aller Pfade zu schaffen erste, Aufzählen sie dann. Für einfache build / util-Skripte (vs High Performance Web-Server) können Sie die Sync-Version ohne Schaden nutzen könnten.

Mit Promises mit ES7

Asynchronous Verwendung mit mz / fs

Das mz Modul bietet Versionen der Kernknotens Bibliothek promisified. Mit ihnen ist einfach. Zuerst die Bibliothek installieren ...

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 der Benutzer einen Wunsch angegeben haben eine rekursive Auflistung (wenn auch nicht in der Frage) zu sehen ... Verwenden 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));

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

Verwendung.

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 ist viel zu optimistisch. Für alles, was ernst, fügen Sie einige Fehlerbehandlung.

nicht-rekursive Version

Was Sie nicht sagen Sie es rekursiv tun wollen, so nehme ich an nur Sie direkte Kinder des Verzeichnisses müssen.

Beispielcode:

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

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

Wie der Knoten v10.10.0 ist es möglich, die neue withFileTypes Option für fs.readdir und fs.readdirSync in Kombination mit der dirent.isDirectory() Funktion Filter für Dateinamen in einem Verzeichnis zu verwenden. Das sieht wie folgt aus:

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

Das zurückgegebene Array ist in der Form:

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

Docs für die fs.Dirent Klasse

Last fs:

const fs = require('fs');

Lesen Sie Dateien async :

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

Lesen Sie Dateien Sync :

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

Get sorted Dateinamen. Sie können die Ergebnisse filtern, basierend auf einem bestimmten extension wie '.txt', '.jpg' und so weiter.

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

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

, wenn jemand noch für diese Suche, ich tue dies:

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 sehr gut für mich

Nahm den allgemeinen Ansatz von @ Hunan-Rostomyan, machte es ein litle prägnante und hinzugefügt excludeDirs Argument. Es wäre trivial mit includeDirs zu erweitern, nur gleiche Muster folgen:

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

Beispiel Nutzung:

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

Sie könnten wollen es auch rekursiv tun.

Es ist ein NPM-Modul für diese:

npm dree

Es ermöglicht Ihnen als String oder ein Objekt eine Darstellung eines Verzeichnisbaum haben. Mit der Datei Rückruf, können Sie auch Ihr Ziel erreichen. Wenn Sie möchten, können Sie auch Weichen Dateierweiterungen angeben zu berücksichtigen.

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

Nur ein Heads-up: Wenn Sie planen, Operationen auf jede Datei in einem Verzeichnis ausführen, versuchen Vinyl -fs (die von schluck , das Streaming-Build-System).

Ich habe ein Knotenmodul um diese Aufgabe zu automatisieren: mddir

Verwendung

node mddir "../ relativ / path /"

So installieren Sie: npm installieren mddir -g

Um aktuelles Verzeichnis zu erzeugen Abschlag: mddir

Zur Erzeugung für jeden absoluten Pfad: mddir / absoluter / path

für einen relativen Pfad zu erzeugen. Mddir ~ / Dokumente / was auch immer

Die md-Datei in Ihrem Arbeitsverzeichnis erzeugt wird.

Zur Zeit ignoriert node_modules und .git Ordner.

Fehlerbehebung

Wenn Sie den Fehler ‚Knoten \ r: Keine solche Datei oder das Verzeichnis‘ erhalten, ist das Problem, dass Ihr Betriebssystem unterschiedliche Zeilenende verwendet und mddir kann sie nicht analysieren, ohne dass Sie explizit die Linie Einstellung zu Unix Endung Stil. Dies wirkt sich in der Regel Windows, aber auch einige Versionen von Linux. Einstellen Zeilenenden zu Unix-Stil hat sich im mddir npm globalen Binärordner durchgeführt werden.

Line Endungen fix

Get npm ist Ordnerpfad mit:

npm config get prefix

Cd in diesen Ordner

BREW installieren dos2unix

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

Dieser wandelt Endungen Unix Leitung anstelle von Dos

Dann normal laufen mit: Knoten mddir“../ relativ / Pfad /".

Beispiel erzeugte Abschlag 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

Verwenden npm list-Inhalte Modul. Es liest den Inhalt und Unter Inhalt des angegebenen Verzeichnisses und gibt die Liste der Dateien und Ordner Pfade.

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

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

Dies ist ein Typoskript, optional rekursiv, optional Fehlerprotokollierung und asynchrone Lösung. Sie können einen regulären Ausdruck für die Dateinamen angeben, den Sie suchen möchten.

Ich habe fs-extra, weil seine eine einfache Super-Set Verbesserung fs.

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
}

Dies funktioniert und das Ergebnis in Test.txt-Datei, die in demselben Verzeichnis vorhanden sein wird

  fs.readdirSync(__dirname).forEach(file => {
    fs.appendFileSync("test.txt", file+"\n", function(err){
    })
})
function getFilesRecursiveSync(dir, fileList, optionalFilterFunction) {
    if (!fileList) {
        grunt.log.error("Variable 'fileList' is undefined or NULL.");
        return;
    }
    var files = fs.readdirSync(dir);
    for (var i in files) {
        if (!files.hasOwnProperty(i)) continue;
        var name = dir + '/' + files[i];
        if (fs.statSync(name).isDirectory()) {
            getFilesRecursiveSync(name, fileList, optionalFilterFunction);
        } else {
            if (optionalFilterFunction && optionalFilterFunction(name) !== true)
                continue;
            fileList.push(name);
        }
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top