简体   繁体   English

NodeJS递归列出目录中的文件

[英]NodeJS recursively list files in directory

I am trying to list all files in a directory (and files within any subdirectories) with the following code:我正在尝试使用以下代码列出目录中的所有文件(以及任何子目录中的文件):

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)

However, when my code attempts to invoke walk(file) on line 8 I get the following error:但是,当我的代码尝试在第 8 行调用walk(file)时,出现以下错误:

TypeError: Cannot call method 'isDirectory' of undefined
    at program.js:7:15
    at Object.oncomplete (fs.js:107:15)

Why is f undefined?为什么 f 未定义? If I have the directory structure below, shouldn't the code identify aaa.txt and bbb.txt as files, my_dir as a directory at which point it recursively calls walk and begins the process again (with zzz.txt being the value of f)?如果我有下面的目录结构,代码不应该将aaa.txtbbb.txt识别为文件, my_dir为目录,此时它递归调用walk并再次开始该过程( zzz.txt是 f 的值)?

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

Function fs.readdir lists the simple file names in that directory, not their absolute path. 函数fs.readdir列出该目录中的简单文件名,而不是它们的绝对路径。 This is why the program failed to find them, thus leading to an error in fs.stat . 这就是程序找不到它们的原因,从而导致fs.stat

Here's the solution: concatenate the directory path name to the file. 这是解决方案:将目录路径名称连接到文件。

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

Here's a version for 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"));
})();

A fully synchronous version, for those situations where you cannot use async:完全同步的版本,适用于无法使用异步的情况:

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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM