如何获取Node.js中目录中所有文件的名称列表?

我试图使用Node.js获取目录中所有文件的名称列表。 我想要的输出是一个文件名数组。 我该怎么做?

您可以使用fs.readdirfs.readdirSync方法。

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

这两种方法的区别在于第一种方法是asynchronous的,所以你必须提供一个callback函数,当读取过程结束时执行。

第二个是同步的,它将返回文件名数组,但是它会停止你的代码的进一步执行,直到读取过程结束。

上面的答案不会执行recursionsearch到目录。 这是我做了recursionsearch(使用节点行走 : 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); }); 

海事组织做这样的任务最方便的方法是使用glob工具。 这是一个node.js的glob包 。 用…安装

 npm install glob 

然后使用通配符来匹配文件名(从包的网站上获取的例子)

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

获取所有子目录中的文件

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

这是一个简单的解决scheme,只使用本机fspath模块:

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

或asynchronous版本(使用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); } }); }); } 

那么你只需要拨打(用于同步版本):

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

或asynchronous版本:

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

不同之处在于节点在执行IO时如何阻塞。 鉴于上面的API是相同的,你可以使用asynchronous版本,以确保最大的性能。

但是使用同步版本有一个好处。 步行完成后,执行一些代码就更容易了,就像在步行之后的下一个语句中一样。 使用asynchronous版本,您需要一些额外的方式来了解何时完成。 也许先创build一个所有path的地图,然后枚举它们。 对于简单的构build/实用脚本(vs高性能Web服务器),您可以使用同步版本而不会造成任何损害。

使用承诺与ES7

asynchronous使用mz / fs

mz模块提供核心节点库的promisified版本。 使用它们很简单。 首先安装库…

 npm install mz 

然后…

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

或者,您可以在ES7中的asynchronous函数中编写它们:

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

更新recursion列表

一些用户已经指定了看到recursion列表的愿望(尽pipe不是在问题中)…使用fs-promise 。 这是围绕mz的薄包装。

 npm install fs-promise; 

然后…

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

依赖。

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

定义。

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

用法。

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

请注意, fileList过于乐观。 对于任何严重的事情,添加一些error handling

你不要说你想recursion的做,所以我假设你只需要直接的子目录。

示例代码:

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

这是一个asynchronousrecursion版本。

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

采取@湖南 – 俄罗斯方丹的一般做法,使其更加简明扼要,并添加了excludeDirs论证。 使用includeDirs扩展会很简单,只需遵循相同的模式:

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

用法示例:

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

加载fs

 const fs = require('fs'); 

读取文件asynchronous

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

读文件同步

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

只是一个问题:如果您打算对目录中的每个文件执行操作,请尝试vinyl-fs (stream量构build系统使用gulp )。

我做了一个节点模块来自动执行这个任务: mddir

用法

节点mddir“../relative/path/”

要安装:npm install mddir -g

为当前目录生成降价:mddir

为任何绝对path生成:mddir / absolute / path

为相对path生成:mddir〜/ Documents / whatever。

md文件在您的工作目录中生成。

目前忽略node_modules和.git文件夹。

故障排除

如果您收到错误“node \ r:没有这样的文件或目录”,问题是您的操作系统使用不同的行尾,而mddir无法parsing它们,而没有明确地将行结束样式设置为Unix。 这通常影响Windows,但也有一些版本的Linux。 将行结尾设置为Unix样式必须在mddir npm全局bin文件夹中执行。

行结尾修复

获取npm bin文件夹path:

npm config get prefix

镉进入该文件夹

brew安装dos2unix

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

这将行结束符转换为Unix而不是DOS

然后像以下那样正常运行:node mddir“../relative/path/”。

生成markdown文件结构的例子'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 
 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); } } }