catDir

I'll give you a simple problem. Find the cats in a directory! Write a function that recursively walks a directory tree and prints the contents of every file, except for those starting with a dot. In NodeJS, using the asynchronous API.

In other words, we're looking for (almost) the equivalent of:

find . -type f -exec cat {} \;

with the difference that it should not search directories that start with a dot, nor include files that start with a dot. I will start optimistic: it's easier to write that in Node than to figure out how to do it with the classic find utility.

In NodeJS

The program isn't very hard to write in plain Node if you have some experience, but it looks ugly:

"use strict";

var fs = require("fs");
var path = require("path");
var sys = require("util");

function catDir(dirname, callback) {
  fs.readdir(dirname, function(err, files){
    if (err) throw new Error(err);
    (function loop(i){
      if (i < files.length) {
        var f = files[i];
        if (f.charAt(0) != ".") {
          var fullname = path.join(dirname, f);
          fs.stat(fullname, function(err, stat){
            if (err) throw new Error(err);
            if (stat.isDirectory()) {
              catDir(fullname, function(){
                loop(i + 1);
              });
            } else if (stat.isFile()) {
              fs.readFile(fullname, "utf8", function(err, data){
                if (err) throw new Error(err);
                sys.puts(data);
                loop(i + 1);
              });
            }
          });
        } else {
          loop(i + 1);
        }
      } else {
        callback();
      }
    })(0);
  });
}

console.time("catDir");
catDir("/home/mishoo/work/my/uglifyjs2/", function(){
  // rest of the program goes here.
  console.timeEnd("catDir");
});

In λanguage

Check it out, simplicity and elegance. It doesn't appear to, but it's still using the asynchronous API — in other words, catDir won't block the process. But there's no callback hell.

catDir = λ(dirname) {
  forEach(readDir(dirname), λ(f){
    if !stringStartsWith(f, ".") {
      let (fullname = pathJoin(dirname, f),
           stat = fstat(fullname)) {
        if isDirectory(stat) {
          catDir(fullname);
        } else if isFile(stat) {
          print(readFile(fullname));
        }
      }
    }
  });
};

catDir("/home/mishoo/work/my/uglifyjs2/");

Notes: