Node.js create folder or use existing

Node.js create folder or use existing

I already have read the documentation of Node.js and, unless if I missed something, it does not tell what the parameters contain in certain operations, in particular fs.mkdir(). As you can see in the documentation, it’s not very much.
Currently, I have this code, which tries to create a folder or use an existing one instead:
fs.mkdir(path,function(e){
if(!e || (e && e.code === ‘EEXIST’)){
//do something with contents
} else {
//debug
console.log(e);
}
});

But I wonder is this the right way to do it? Is checking for the code EEXIST the right way to know that the folder already exists? I know I can do fs.stat() before making the directory, but that would already be two hits to the filesystem.
Secondly, is there a complete or at least a more detailed documentation of Node.js that contains details as to what error objects contain, what parameters signify etc.

Solutions/Answers:

Solution 1:

Good way to do this is to use mkdirp module.

$ npm install mkdirp

Use it to run function that requires the directory. Callback is called after path is created or if path did already exists. Error err is set if mkdirp failed to create directory path.

var mkdirp = require('mkdirp');
mkdirp('/tmp/some/path/foo', function(err) { 

    // path exists unless there was an error

});

Solution 2:

Edit: Because this answer is very popular, I have updated it to reflect up-to-date practices.

Using a try {} catch (err) {}, you can achieve this very gracefully without encountering a race condition.

Related:  Pass an extra argument to a callback function

In order to prevent dead time between checking for existence and creating the directory, we simply try to create it straight up, and disregard the error if it is EEXIST (directory already exists).

If the error is not EEXIST, however, we ought to throw an error, because we could be dealing with something like an EPERM or EACCES

We also can use the recursive option of mkdir in order to have a behaviour like mkdir -p (Note: only available in Node >=10.x)

Sync version

const fs = require('fs')

function ensureDirSync (dirpath) {
  try {
    fs.mkdirSync(dirpath, { recursive: true })
  } catch (err) {
    if (err.code !== 'EEXIST') throw err
  }
}

try {
  ensureDirSync('a/b/c')
  console.log('Directory created')
} catch (err) {
  console.error(err)
}

Async version (async/await, modern Node versions)

const fs = require('fs').promises

async function ensureDir (dirpath) {
  try {
    await fs.mkdir(dirpath, { recursive: true })
  } catch (err) {
    if (err.code !== 'EEXIST') throw err
  }
}

async function main () {
  try {
    await ensureDir('a/b/c')
    console.log('Directory created')
  } catch (err) {
    console.error(err)
  }
}

main()

If you prefer not to use the experimental fs.promises API (though it’s stable, and is here to stay), you can wrap fs.mkdir yourself:

await new Promise((resolve, reject) => {
  fs.mkdir(dirpath, { recursive: true }, err => err ? reject(err) : resolve())
})

Async version (promises, legacy Node versions)

Note: Because we don’t have the new recursive option in pre-10.x Node versions, we have to ensure every part of the path is created.

const fs = require('fs')

function ensureDir (dirpath) {
  return fs.mkdir(dirpath, function (err) {
    if (err.code === 'EEXIST') {
      return Promise.resolve()
    } else {
      return Promise.reject(err)
    }
  })
}

Promise.resolve()
  .then(function () { ensureDir('a') })
  .then(function () { ensureDir('a/b') })
  .then(function () { ensureDir('a/b/c') })
  .then(function () { console.log('Directory created') })
  .catch(function () { console.error(err) })

Solution 3:

If you want a quick-and-dirty one liner, use this:

fs.existsSync("directory") || fs.mkdirSync("directory");

Solution 4:

The node.js docs for fs.mkdir basically defer to the Linux man page for mkdir(2). That indicates that EEXIST will also be indicated if the path exists but isn’t a directory which creates an awkward corner case if you go this route.

Related:  How to generate sequence of numbers/chars in javascript?

You may be better off calling fs.stat which will tell you whether the path exists and if it’s a directory in a single call. For (what I’m assuming is) the normal case where the directory already exists, it’s only a single filesystem hit.

These fs module methods are thin wrappers around the native C APIs so you’ve got to check the man pages referenced in the node.js docs for the details.

Solution 5:

You can use this:

if(!fs.existsSync("directory")){
    fs.mkdirSync("directory", 0766, function(err){
        if(err){
            console.log(err);
            // echo the result back
            response.send("ERROR! Can't make the directory! \n");
        }
    });
}

Solution 6:

I propose a solution without modules (accumulate modules is never recommended for maintainability especially for small functions that can be written in a few lines…) :

LAST UPDATE :

In v10.12.0, NodeJS impletement recursive options :

// Create recursive folder
fs.mkdir('my/new/folder/create', { recursive: true }, (err) => { if (err) throw err; });

UPDATE :

// Get modules node
const fs   = require('fs');
const path = require('path');

// Create 
function mkdirpath(dirPath)
{
    if(!fs.accessSync(dirPath, fs.constants.R_OK | fs.constants.W_OK))
    {
        try
        {
            fs.mkdirSync(dirPath);
        }
        catch(e)
        {
            mkdirpath(path.dirname(dirPath));
            mkdirpath(dirPath);
        }
    }
}

// Create folder path
mkdirpath('my/new/folder/create');