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

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

1427419 次浏览

您可以使用#0#1方法。fs包含在Node.js核心中,因此无需安装任何东西。

fs.readdir

const testFolder = './tests/';const fs = require('fs');
fs.readdir(testFolder, (err, files) => {files.forEach(file => {console.log(file);});});

fs.readdir同步

const testFolder = './tests/';const fs = require('fs');
fs.readdirSync(testFolder).forEach(file => {console.log(file);});

这两种方法的区别在于,第一种方法是异步的,因此您必须提供一个回调函数,该函数将在读取过程结束时执行。

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

不过,上面的答案并没有对目录执行递归搜索。这是我为递归搜索所做的(使用节点游走npm install walk

var walk    = require('walk');var files   = [];
// Walker optionsvar walker  = walk.walk('./test', { followLinks: false });
walker.on('file', function(root, stat, next) {// Add this file to the list of filesfiles.push(root + '/' + stat.name);next();});
walker.on('end', function() {console.log(files);});

获取所有子目录中的文件

const fs=require('fs');
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'))

这是一个异步递归版本。

    function ( path, callback){// the callback gets ( err, files) where files is an array of file namesif( typeof callback !== 'function' ) returnvarresult = [], 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 errorelse 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()}
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);}}}

只是提醒一下:如果您计划对目录中的每个文件执行操作,请尝试vinyl-fs(流构建系统吞咽使用它)。

在我看来,执行此类任务的最方便方法是使用球状工具。这是node.js.安装的全局包

npm install glob

然后使用通配符来匹配文件名(示例取自包的网站

var glob = require("glob")
// options is optionalglob("**/*.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.})

如果您计划使用Globby,这里有一个查找当前文件夹下的任何xml文件的示例

var globby = require('globby');
const paths = await globby("**/*.xml");

这是一个简单的解决方案,仅使用本机fspath模块:

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

或异步版本(使用fs.readdir代替):

// async version with basic error handlingfunction 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"...});

或异步版本:

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

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

然而,使用同步版本有一个优点。更容易在行走完成后立即执行一些代码,就像在行走后的下一条语句中一样。使用异步版本,你需要一些额外的方法来知道你何时完成。也许首先创建所有路径的映射,然后枚举它们。对于简单的构建/util脚本(与高性能Web服务器相比),你可以使用同步版本而不会造成任何损坏。

依赖关系。

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 DIRfileList(DIR);// => ['/usr/local/bin/babel', '/usr/local/bin/bower', ...]
// 2. List all file names in DIRfileList(DIR).map((file) => file.split(path.sep).slice(-1)[0]);// => ['babel', 'bower', ...]

请注意,fileList过于乐观。对于任何严重的事情,添加一些错误处理。

沿用了@湖南-罗斯托姆扬的一般思路,稍微精简了一点,增加了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']));

在ES7中使用Promises

与mz/fs异步使用

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

npm install mz

那…

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

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

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

递归列表更新

一些用户指定了查看递归列表的愿望(尽管不在问题中)…使用#0。它是围绕#1的一个薄包装器。

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

非递归版本

您没有说您想递归执行此操作,因此我假设您只需要目录的直接子项。

示例代码:

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

加载fs

const fs = require('fs');

读取文件async

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

读取文件同步

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

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

用法

节点mddir"…/相对/路径/"

安装:npm install mddir-g

为当前目录生成降价:mddir

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

为相对路径生成:mddir~/Documents/无论什么。

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

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

故障排除

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

线路末端固定

获取npm bin文件夹路径:

npm config get prefix

cd到那个文件夹

brew安装doc2unix

lib/node_modules/mddir/src/mddir.js

这将行结尾转换为Unix而不是Dos

然后正常运行:节点mddir“…/相对/路径/”。

示例生成的降价文件结构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

获取sorted文件名。您可以根据特定的extension过滤结果,例如'.txt''.jpg'等。

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

使用npm列表内容列表模块。它读取给定目录的内容和子内容,并返回文件和文件夹路径列表。

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

如果有人还在找这个,我这样做:

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

它的工作对我来说非常好

从Node v10.10.0开始,可以将#1#2的新withFileTypes选项与#3函数结合使用来过滤目录中的文件名。如下所示:

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

返回的数组的形式为:

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

这是一个TypeScript、可选递归、可选错误记录和异步解决方案。您可以为要查找的文件名指定正则表达式。

我使用了fs-extra,因为它是对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 folderlet 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 furtherfolderDepth = folderDepth - 1
// Loop through the results, possibly recursefor (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' filesresults.push(...(await FileHelper.findFiles(fullPath, filePattern, errors, folderDepth)))} else {// Filter by the file name pattern, if there is oneif (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}

这将工作并将结果存储在test.txt文件这将是目前在同一目录

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

从盒子里出来

如果你想要一个具有目录结构的对象开箱即用,我强烈建议你检查目录树

假设你有这样的结构:

photos│   june│   └── windsurf.jpg└── january├── ski.png└── snowboard.jpg
const dirTree = require("directory-tree");const tree = dirTree("/path/to/photos");

将返回:

{path: "photos",name: "photos",size: 600,type: "directory",children: [{path: "photos/june",name: "june",size: 400,type: "directory",children: [{path: "photos/june/windsurf.jpg",name: "windsurf.jpg",size: 400,type: "file",extension: ".jpg"}]},{path: "photos/january",name: "january",size: 200,type: "directory",children: [{path: "photos/january/ski.png",name: "ski.png",size: 100,type: "file",extension: ".png"},{path: "photos/january/snowboard.jpg",name: "snowboard.jpg",size: 100,type: "file",extension: ".jpg"}]}]}

自定义对象

否则,如果您想创建带有自定义设置的目录树对象,请查看以下片段。此代码框上可以看到一个实时示例。

// my-script.jsconst fs = require("fs");const path = require("path");
const isDirectory = filePath => fs.statSync(filePath).isDirectory();const isFile = filePath => fs.statSync(filePath).isFile();
const getDirectoryDetails = filePath => {const dirs = fs.readdirSync(filePath);return {dirs: dirs.filter(name => isDirectory(path.join(filePath, name))),files: dirs.filter(name => isFile(path.join(filePath, name)))};};
const getFilesRecursively = (parentPath, currentFolder) => {const currentFolderPath = path.join(parentPath, currentFolder);let currentDirectoryDetails = getDirectoryDetails(currentFolderPath);
const final = {current_dir: currentFolder,dirs: currentDirectoryDetails.dirs.map(dir =>getFilesRecursively(currentFolderPath, dir)),files: currentDirectoryDetails.files};
return final;};
const getAllFiles = relativePath => {const fullPath = path.join(__dirname, relativePath);const parentDirectoryPath = path.dirname(fullPath);const leafDirectory = path.basename(fullPath);
const allFiles = getFilesRecursively(parentDirectoryPath, leafDirectory);return allFiles;};
module.exports = { getAllFiles };

然后你可以简单地做:

// another-file.js
const { getAllFiles } = require("path/to/my-script");
const allFiles = getAllFiles("/path/to/my-directory");

我从你的问题中假设你不想要目录名称,只是文件。

目录结构示例

animals├── all.jpg├── mammals│   └── cat.jpg│   └── dog.jpg└── insects└── bee.jpg

Walk函数

点数转到这一要点中的Justin Maier

如果您想要只是一个数组的文件路径使用return_object: false

const fs = require('fs').promises;const path = require('path');
async function walk(dir) {let files = await fs.readdir(dir);files = await Promise.all(files.map(async file => {const filePath = path.join(dir, file);const stats = await fs.stat(filePath);if (stats.isDirectory()) return walk(filePath);else if(stats.isFile()) return filePath;}));
return files.reduce((all, folderContents) => all.concat(folderContents), []);}

用法

async function main() {console.log(await walk('animals'))}

产出

["/animals/all.jpg","/animals/mammals/cat.jpg","/animals/mammals/dog.jpg","/animals/insects/bee.jpg"];

我最近为此构建了一个工具,它可以做到这一点……它异步获取目录并返回项目列表。您可以获取目录、文件或两者兼而有之,文件夹是第一个。如果您不想获取整个文件夹,您还可以对数据进行分页。

https://www.npmjs.com/package/fs-browser

这是链接,希望对大家有帮助!

我通常使用:FS-Extra

const fileNameArray = Fse.readdir('/some/path');

结果:

["b7c8a93c-45b3-4de8-b9b5-a0bf28fb986e.jpg","daeb1c5b-809f-4434-8fd9-410140789933.jpg"]

我的2美分如果有人:

只是想从他们项目的本地子文件夹中列出文件名(不包括目录)

  • ✅无额外依赖
  • ✅1功能
  • ✅标准化路径(Unix vs. Windows)
const fs = require("fs");const path = require("path");
/*** @param {string} relativeName "resources/foo/goo"* @return {string[]}*/const listFileNames = (relativeName) => {try {const folderPath = path.join(process.cwd(), ...relativeName.split("/"));return fs.readdirSync(folderPath, { withFileTypes: true }).filter((dirent) => dirent.isFile()).map((dirent) => dirent.name.split(".")[0]);} catch (err) {// ...}};
README.mdpackage.jsonresources|-- countries|-- usa.yaml|-- japan.yaml|-- gb.yaml|-- provinces|-- .........

listFileNames("resources/countries") #=> ["usa", "japan", "gb"]

如果上面的许多选项看起来太复杂或不复杂,您在这里寻找的是另一种使用node-dir-https://github.com/fshost/node-dir的方法

npm install node-dir

这是一个列出在子目录中搜索的所有. xml文件的函数

import * as nDir from 'node-dir' ;
listXMLs(rootFolderPath) {let xmlFiles ;
nDir.files(rootFolderPath, function(err, items) {xmlFiles = items.filter(i => {return path.extname(i) === '.xml' ;}) ;console.log(xmlFiles) ;});}

使用平面图

function getFiles(dir) {return fs.readdirSync(dir).flatMap((item) => {const path = `${dir}/${item}`;if (fs.statSync(path).isDirectory()) {return getFiles(path);}
return path;});}

给定以下目录:

dist├── 404.html├── app-AHOLRMYQ.js├── img│   ├── demo.gif│   └── start.png├── index.html└── sw.js

用法:

getFiles("dist")

输出:

['dist/404.html','dist/app-AHOLRMYQ.js','dist/img/demo.gif','dist/img/start.png','dist/index.html']

我的一个班轮代码:

const fs = require("fs")const path = 'somePath/'
const filesArray = fs.readdirSync(path).filter(file => fs.lstatSync(path+file).isFile())

它只有2行代码:

fs=require('fs')fs.readdir("./img/", (err,filename)=>console.log(filename))

图片:aakash4dev

试试这个,对我有用

import fs from 'fs/promises';const path = 'path/to/folder';
async function readDir(path) {const files= await fs.readdir(path);console.log(files); // array of file names}