在NodeJS中递归列出目录中的文件

7

我正在尝试使用以下代码列出目录中的所有文件(以及任何子目录中的文件):

var fs = require('fs')

var walk = function(directoryName) {
  fs.readdir(directoryName, function(e, files) {
    files.forEach(function(file) {
      fs.stat(file, function(e, f) {
        if (f.isDirectory()) {
          walk(file)
        } else {
          console.log('- ' + file)
        }
      })
    })
  })
}

walk(__dirname)

然而,当我的代码第8行企图调用walk(file)时,我得到以下错误:
TypeError: Cannot call method 'isDirectory' of undefined
    at program.js:7:15
    at Object.oncomplete (fs.js:107:15)

为什么f未定义?如果我有以下目录结构,代码不应该将aaa.txtbbb.txt识别为文件,将my_dir识别为一个目录,然后递归调用walk并再次开始过程(以zzz.txt作为f的值)吗?

- aaa.txt
- bbb.txt
+ my_dir
    - zzz.txt

2
尝试测试 e,可能出现了错误。 - E net4
1
你需要将你的 directoryName 也加入到递归遍历中。 - wayne
4个回答

8

fs.readdir函数列出的是目录下简单的文件名,而不是它们的绝对路径。这就是为什么程序无法找到它们,从而导致fs.stat出现错误。

解决方法:将目录路径名与文件名连接起来。

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

var walk = function(directoryName) {
  fs.readdir(directoryName, function(e, files) {
    if (e) {
      console.log('Error: ', e);
      return;
    }
    files.forEach(function(file) {
      var fullPath = path.join(directoryName,file);
      fs.stat(fullPath, function(e, f) {
        if (e) {
          console.log('Error: ', e);
          return;
        }
        if (f.isDirectory()) {
          walk(fullPath);
        } else {
          console.log('- ' + fullPath);
        }
      });
    });
  });
};

1

完全同步版本,适用于无法使用异步的情况:

const walk = (dir, files = []) => {
    const dirFiles = fs.readdirSync(dir)
    for (const f of dirFiles) {
        const stat = fs.lstatSync(dir + path.sep + f)
        if (stat.isDirectory()) {
            walk(dir + path.sep + f, files)
        } else {
            files.push(dir + path.sep + f)
        }
    }
    return files
}
const allFiles = walk(someDir)

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

var walk = function(directoryName) {

  fs.readdir(directoryName, function(e, files) {
    files.forEach(function(file) {
      fs.stat(directoryName + path.sep + file, function(e, f) {

        if (f.isDirectory()) {
          walk(directoryName + path.sep + file)
        } else {
          console.log(' - ' + file)
        }
      })
    })
  })
}

walk(__dirname)

1
这是一个针对async/await的版本:
const { promises: fs } = require("fs");
const path = require("path");

async function walk(dir) {
    const entries = await fs.readdir(dir);
    let ret = [];
    for (const entry of entries) {
        const fullpath = path.resolve(dir, entry);
        const info = await fs.stat(fullpath);
        if (info.isDirectory()) {
            ret = [...ret, ...(await walk(fullpath))];
        } else {
            ret = [...ret, fullpath];
        }
    }
    return ret;
}

(async function () {
    console.log(await walk("/path/to/some/dir"));
})();


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接