Node.js 递归列出文件的完整路径

Node.js recursively list full path of files

大家晚安。我可能在使用一些简单的递归函数时遇到了麻烦。问题是递归地列出给定文件夹及其子文件夹中的所有文件。

目前,我已经设法使用一个简单的函数列出目录中的文件:

fs.readdirSync(copyFrom).forEach((file) => {
  let fullPath = path.join(copyFrom, file);

  if (fs.lstatSync(fullPath).isDirectory()) {
    console.log(fullPath);
  } else {
    console.log(fullPath);
  }
});

我试过各种方法,比如do{} ... while(),但我做不对。由于我是javascript的初学者,我最终决定向你们寻求帮助。

只需添加一个递归调用即可:

 function traverseDir(dir) {
   fs.readdirSync(dir).forEach(file => {
     let fullPath = path.join(dir, file);
     if (fs.lstatSync(fullPath).isDirectory()) {
        console.log(fullPath);
        traverseDir(fullPath);
      } else {
        console.log(fullPath);
      }  
   });
 }

以这种方式使用 console.log 可以显示路径,这很好,但是如果您想对路径做一些更有意义的事情怎么办?例如,也许您想将它们全部收集到一个数组中,然后将它们传递到其他地方进行处理...

这种从种子状态开始并在状态变化时扩展值序列的过程称为 unfold

const { join } =
  require ('path')

const { readdirSync, statSync } =
  require ('fs')

const unfold = (f, initState) =>
  f ( (value, nextState) => [ value, ...unfold (f, nextState) ]
    , () => []
    , initState
    )

const None =
  Symbol ()

const relativePaths = (path = '.') =>
  readdirSync (path) .map (p => join (path, p))

const traverseDir = (dir) =>
  unfold
    ( (next, done, [ path = None, ...rest ]) =>
        path === None
          ? done ()
          : next ( path
                 , statSync (path) .isDirectory ()
                     ? relativePaths (path) .concat (rest)
                     : rest
                 )
    , relativePaths (dir)
    )

console.log (traverseDir ('.'))
// [ a, a/1, a/1/1, a/2, a/2/1, a/2/2, b, b/1, ... ]

如果这是您第一次看到这样的节目,unfold 会感到非常不知所措。下面是 unfold 的简化示例,用于生成小写 alphabet

的数组

const unfold = (f, init) =>
  f ( (x, next) => [ x, ...unfold (f, next) ]
    , () => []
    , init
    )

const nextLetter = c =>
  String.fromCharCode (c.charCodeAt (0) + 1)

const alphabet =
  unfold
    ( (next, done, c) =>
        c > 'z'
          ? done ()
          : next ( c              // value to add to output
                 , nextLetter (c) // next state
                 )
    , 'a' // initial state
    )

console.log (alphabet)
// [ a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z ]

如果您仍然卡住了,我在此处演示的技术在类似问题的回答中有更详细的解释

一般来说,最好使用fs模块中的异步函数,因为这样可以防止程序在磁盘读取时间过长或网络延迟时挂起。正如其他问答

中所展示的那样,展开可以很好地处理异步
  • Recursion call async func with promises gets Possible Unhandled Promise Rejection