Introduction

This tutorial introduce the asynchronous recursive directory search using Node.js fs.readdir.

Solution

In general, there are two ways to accomplish the asynchronous recursive directory search using Node.js fs.readdir.

In asynchronous environment, there are two kind of loops:

  • Serial loop: A serial loop waits for one iteration to complete before it moves onto the next iteration - this guarantees that every iteration of the loop completes in order.
  • Parallel loop: In a parallel loop, all the iterations are started at the same time, and one may complete before another, however, it is much faster than a serial loop.

How to choose the loops?

You probably better to use parallel loop when it doesn't matter what order it should complete, just as long as it completes and returns. But, you should use serial loop when you want the result in order.

Parallel loop to async directory search

var fs = require('fs');
var path = require('path');
 
var readFile = function(dir, done) {
  var results = [];
  fs.readdir(dir, function(err, list) {
    if (err) { return done(err);}
 
    var pending = list.length;
    if (!pending){ return done(null, results);}
    list.forEach(function(file) {
      file = path.resolve(dir, file);
      fs.stat(file, function(err, stat) {
        if (stat && stat.isDirectory()) {
          readFile(file, function(err, res) {
            results = results.concat(res);
            if (!--pending) done(null, results);
          });
        } else {
          results.push(file);
          if (!--pending) done(null, results);
        }
      });
    });
  });
};
 
// test it out on home directory
walk(process.env.HOME, function(err, results) {
  if (err) throw err;
  console.log(results);
});

Serial loop to async directory search

var fs = require('fs');
var walk = function(dir, done) {
  var results = [];
  fs.readdir(dir, function(err, list) {
    if (err) return done(err);
    var i = 0;
    (function next() {
      var file = list[i++];
      if (!file) return done(null, results);
      file = dir + '/' + file;
      fs.stat(file, function(err, stat) {
        if (stat && stat.isDirectory()) {
          walk(file, function(err, res) {
            results = results.concat(res);
            next();
          });
        } else {
          results.push(file);
          next();
        }
      });
    })();
  });
};
 
// test it out on home directory
walk(process.env.HOME, function(err, results) {
  if (err) throw err;
  console.log(results);
});

References & Resources

  • http://stackoverflow.com/questions/5827612/node-js-fs-readdir-recursive-directory-search