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


当前回答

下面是一个仅使用本机fs和路径模块的简单解决方案:

// 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.readder):

// 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服务器相比),您可以使用同步版本而不会造成任何损坏。

其他回答

非递归版本

您并没有说要递归地执行,所以我假设您只需要目录的直接子级。

示例代码:

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

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

从Node v10.10.0开始,可以将fs.readdir和fs.readderSync的新withFileTypes选项与dirent.isDirectory()函数结合使用,以过滤目录中的文件名。看起来像这样:

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

返回的数组的格式为:

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

下面是一个仅使用本机fs和路径模块的简单解决方案:

// 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.readder):

// 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服务器相比),您可以使用同步版本而不会造成任何损坏。

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

目录结构示例

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

步行功能

根据这一要点,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"
];

这将起作用,并将结果存储在test.txt文件中,该文件将位于同一目录中

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