Making directory along with missing parents in Node.js


Note: By the time this post is written, the Node.js is on version 0.6.10. Therefore anything in this post may or may not valid in the newer versions.

Node.js file system API provide a bunch of functions to read/write files. One of them is the fs.mkdir(path, [mode], [callback]). However, this function itself does not provide any option for you to create a directory if the parents folder is missing, it’ll trigger an exception if you trying to do so. In another word, you can’t do something like “mkdir -p DIR”.

However, the callback function is an extreamly useful feature to extend this function. In case the fs.mkdir failed, it passes an error object into the callback function. Like this:

var fs = require('fs');
fs.mkdir('parent/child', function(error) {
  console.log(error);
});

You’ll see it print an object looks like:

{ [Error: ENOENT, no such file or directory ‘parent/child’] errno: 34, code: ‘ENOENT’, path: ‘parent/child’ }

Good, now we know in the case of missing directory, we’ll get error code 34. What if we catch the error and try to recursively create it’s parent, then create the directory again? Everybody deserve a second chance, right?

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

fs.mkdirParent = function(dirPath, mode, callback) {
  //Call the standard fs.mkdir
  fs.mkdir(dirPath, mode, function(error) {
    //When it fail in this way, do the custom steps
    if (error && error.errno === 34) {
      //Create all the parents recursively
      fs.mkdirParent(path.dirname(dirPath), mode, callback);
      //And then the directory
      fs.mkdirParent(dirPath, mode, callback);
    }
    //Manually run the callback since we used our own callback to do all these
    callback && callback(error);
  });
};

Now you can run it like this;

fs.mkdirParent('a/b/c/d/e');

8 responses to “Making directory along with missing parents in Node.js”

  1. Awesome codes! The original codes has some issue with the callback. Your code makes sure the callback only called once.

  2. A constructive comment would be more interesting….
    Trying to show how things work is always welcome and installing modules is not always the best approach or needed.

  3. it should be:
    function mkdir(dirPath, mode,callback)
    {
    fs.mkdir(dirPath, mode, function (error)
    {
    if (error && error.code == ‘ENOENT’)
    {
    mkdir(path.dirname(dirPath), mode, mkdir.bind(this,dirPath,mode,callback));
    }
    else if (callback) callback(error);
    });
    }

  4. Great, the script works fine except that I think the most used pattern would be to do something (callback) once the last directory is created.
    From my test what currently happens is that the callback is executed for every directory created.
    Am I doing something wrong or is this the expected behaviour, and if so, how can I only have one callback once the path is fully created?

    Thanks
    Luis

  5. Don’t meant to reinvent the wheel. The point of this snippet is NOT to install any module and still able to have a short script up and running.

Leave a Reply

Your email address will not be published.