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

javascript node.js

606951 观看

16回复

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

作者: resopollution 的来源 发布者: 2019 年 6 月 8 日

回应 (16)


904

决定

您可以使用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);
})

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

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

作者: CMS 发布者: 28.04.2010 06:15

167

上面的答案虽然没有对目录进行递归搜索。下面是我做了一个递归搜索(使用节点行走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);
});
作者: Ruben Tan 发布者: 27.04.2011 07:35

162

IMO最方便的方法就是使用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.
})
作者: KFL 发布者: 30.08.2014 07:57

76

获取所有子目录中的文件

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'))
作者: Tito100 发布者: 11.12.2013 05:25

50

这是一个只使用本机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);
        }
    });
}

或异步版本(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"...
});

或异步版本:

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

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

但是,使用同步版本有一个优点。步行完成后,执行某些代码会更容易,如步行后的下一个语句。使用异步版本,您需要一些额外的方法来了解何时完成。也许首先创建所有路径的地图,然后枚举它们。对于简单的build / util脚本(与高性能Web服务器相比),您可以使用同步版本而不会造成任何损坏。

作者: Ali 发布者: 03.02.2015 12:54

19

在ES7中使用Promise

与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中的异步函数中编写它们:

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

递归列表的更新

一些用户已经指定了查看递归列表的愿望(虽然不在问题中)...使用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));
作者: Evan Carroll 发布者: 30.05.2016 06:48

13

依赖。

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太乐观了。对于任何严重的,添加一些错误处理。

作者: Hunan Rostomyan 发布者: 13.11.2015 03:31

9

你不是说你想要递归地做,所以我假设你只需要目录的直接子项。

示例代码:

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

fs.readdirSync('your-directory-path')
  .filter((file) => fs.lstatSync(path.join(folder, file)).isFile());
作者: Tyler Long 发布者: 01.07.2016 02:25

6

装载fs

const fs = require('fs');

读取文件异步

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

读取文件同步

var files = fs.readdirSync('./dir');
作者: Eduardo Cuomo 发布者: 13.09.2016 05:12

4

这是一个异步递归版本。

    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()
    }
作者: Oggy Transfluxitor Jones 发布者: 01.03.2014 08:57

3

采用了@ Hunan-Rostomyan的一般方法,使其更加简洁,增添了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']));
作者: A T 发布者: 15.01.2016 12:28

2

获取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();
}
作者: Yas 发布者: 21.02.2018 02:45

0

只是抬头:如果您计划对目录中的每个文件执行操作,请尝试使用vinyl-fs(由gulp(流式构建系统)使用)。

作者: XåpplI'-I0llwlg'I - 发布者: 12.06.2014 05:54

0

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

用法

node mddir“../relative/path/”

要安装:npm install mddir -g

要为当前目录生成markdown:mddir

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

为相对路径生成:mddir~ / Documents / whatever。

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

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

故障排除

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

行结尾修复

获取npm bin文件夹路径:

npm config get prefix

Cd进入该文件夹

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
作者: John Byrne 发布者: 28.10.2017 03:52

0

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

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

list("./dist",(o)=>{
  if(o.error) throw o.error;
   console.log('Folders: ', o.dirs);
   console.log('Files: ', o.files);
});
作者: Paweł 发布者: 23.07.2018 10:49

-1

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);
        }
    }
}
作者: Francois 发布者: 01.04.2014 03:35
32x32