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?
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.
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);
});
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.
})
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'))
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.
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 ) }
};
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));
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.
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());
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');
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']));
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();
}
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
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
}
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']
Verwenden Sie npm
list-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);
});
Ich habe ein Knotenmodul erstellt, um diese Aufgabe zu automatisieren: mddir
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.
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.
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/".
|-- .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
Sie können es auch rekursiv machen.
Dafür gibt es ein NPM-Modul:
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
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){
})
})