237

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.

1
  • 34
    Small nitpick, but get rid of the e &&. If !e fails, then you know e is truthy. Commented Dec 4, 2012 at 4:46

15 Answers 15

283
+300

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

Node >=10

The new { recursive: true } option of Node's fs now allows this natively. This option mimics the behaviour of UNIX's mkdir -p. It will recursively make sure every part of the path exist, and will not throw an error if any of them do.

(Note: it might still throw errors such as EPERM or EACCESS, so better still wrap it in a try {} catch (e) {} if your implementation is susceptible to it.)

Synchronous version.

fs.mkdirSync(dirpath, { recursive: true })

Async version

await fs.promises.mkdir(dirpath, { recursive: true })

Older Node versions

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

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

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

For mkdir -p-like recursive behaviour, e.g. ./a/b/c, you'd have to call it on every part of the dirpath, e.g. ./a, ./a/b, .a/b/c

Sign up to request clarification or add additional context in comments.

6 Comments

var fs = Npm.require('fs'); var dir = process.env.PWD + '/files/users/' + this.userId + '/'; try { fs.mkdirSync(dir); } catch (e) { if (e.code != 'EEXIST') throw e; }
I tried your code, create a js-script that uses the catalog creation like this: mkdirpSync(path.join(__dirname, 'first', 'second', 'third', 'ololol', 'works')); But got this error: $ node 1.js fs.js:747 return binding.mkdir(pathModule._makeLong(path), ^ Error: EPERM, operation not permitted 'C:\' at Error (native) at Object.fs.mkdirSync (fs.js:747:18) at mkdirpSync (C:\Users\MAXIM\Desktop\test\1.js:15:8) at Object.<anonymous> (C:\Users\MAXIM\Desktop\test\1.js:19:1) ... Could you suggest what could be wrong? Used on windows obviously :)
EPERM seems like a permission issue, so the script would haven broken execution anyway
I think that would be better: var mkdirpSync = function (dirpath) { var parts = dirpath.split(path.sep); for( var i = 1; i <= parts.length; i++ ) { try { fs.mkdirSync( path.join.apply(null, parts.slice(0, i)) ); } catch (error) { if ( error.code != 'EEXIST' ){ throw error; } } } }
warning: it doesn't work if your path starts with a /
|
244

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

});

13 Comments

It seems to me the correct (read 'no-dependency-added') answer would be the one down low, by @Raugaral, using fs.exists(Sync).
@RicardoPedroni The correct way is to use a module. Modules are usually whole-heartedly trying to solve one problem, and are often maintained. You can update them easily with npm. Also, you should specifically avoid using fs.exists[Sync] as its use implies race conditions.
@1j01 I don't believe the correct way is to use a module if the platform natively supports the operation. That's a road to chaos. I have to agree that there are better answers from a technical standpoint.
@1j01 Also, using Sync operations imply race conditions because their use is a resolution to them.
Why would you not use the internal node fs functionality?
|
76

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

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

5 Comments

fs.existsSync(...) is not deprecated, though, so this answer seems ok.
Heads up! Won't work for "dir/foo/bar" i.e lacks the mkdir -p flag feature
This also has a race condition
With @christophe-marois answer's recursive flag, the equivalent to POSIX mkdir -p flag is included and it also works for folders missing in the path: fs.existsSync("dir/foo/bar") || fs.mkdirSync("dir/foo/bar", {recursive: true}).
27

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.

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.

1 Comment

Calling stat before mkdir has the potential for a race condition -- bear this in mind.
26

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");
        }
    });
}

5 Comments

-1. I don't believe this works, statSync will throw an error if the entity does not exist at all, crashing the code. You need to wrap this in a try/catch block.
Sorry, i'm wrong. change "statSync" for "existsSync"
According to nodejs.org/api/fs.html#fs_fs_mkdirsync_path_mode the Sync variant of mkdir does not accept a callback
According to nodejs.org/api/fs.html#fs_fs_existssync_path, fs.existsSync() and fs.exists() will be deprecated.
Wrong. fs.exists() has been deprecated due to incompatible callback params. The fs.existsSync() method still works.
9

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');

5 Comments

fs.exists() is deprecated in node v9. use fs.access() instead. (returns undefined if the file exists; otherwise throws an error ENOENT)
Without any npm package, it's working. It a valuable code. Thanks
This one is quite better for creating a folder under existing long path ;) Thanks, man.
What about fs.mkdirSync('my/new/folder/create', {recursive: true}) ?
Thanks ! I update my post to help others. Node 10.12.0 was too recent.
5

Here is the ES6 code which I use to create a directory (when it doesn't exist):

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

function createDirectory(directoryPath) {
  const directory = path.normalize(directoryPath);

  return new Promise((resolve, reject) => {
    fs.stat(directory, (error) => {
      if (error) {
        if (error.code === 'ENOENT') {
          fs.mkdir(directory, (error) => {
            if (error) {
              reject(error);
            } else {
              resolve(directory);
            }
          });
        } else {
          reject(error);
        }
      } else {
        resolve(directory);
      }
    });
  });
}

const directoryPath = `${__dirname}/test`;

createDirectory(directoryPath).then((path) => {
  console.log(`Successfully created directory: '${path}'`);
}).catch((error) => {
  console.log(`Problem creating directory: ${error.message}`)
});

Note:

  • In the beginning of the createDirectory function, I normalize the path to guarantee that the path seperator type of the operating system will be used consistently (e.g. this will turn C:\directory/test into C:\directory\test (when being on Windows)
  • fs.exists is deprecated, that's why I use fs.stat to check if the directory already exists
  • If a directory doesn't exist, the error code will be ENOENT (Error NO ENTry)
  • The directory itself will be created using fs.mkdir
  • I prefer the asynchronous function fs.mkdir over it's blocking counterpart fs.mkdirSync and because of the wrapping Promise it will be guaranteed that the path of the directory will only be returned after the directory has been successfully created

1 Comment

Thank you for a clean solution that does not involve unnecessary modules. It worked perfectly for me. I wish there were more answers like this!
4

You can also use fs-extra, which provide a lot frequently used file operations.

Sample Code:

var fs = require('fs-extra')

fs.mkdirs('/tmp/some/long/path/that/prob/doesnt/exist', function (err) {
  if (err) return console.error(err)
  console.log("success!")
})

fs.mkdirsSync('/tmp/another/path')

docs here: https://github.com/jprichardson/node-fs-extra#mkdirsdir-callback

Comments

3

You'd better not to count the filesystem hits while you code in Javascript, in my opinion. However, (1) stat & mkdir and (2) mkdir and check(or discard) the error code, both ways are right ways to do what you want.

2 Comments

It's a good way to mkdir a directory or use existing one. I don't see why you don't see. Checking the error code is polite good one, while discarding the error code is just a good one. don't you agree?
I see what's your point. However, I believe that there are many ways to do things right. Thanks.
2

create dynamic name directory for each user... use this code

***suppose email contain user mail address***

var filessystem = require('fs');
var dir = './public/uploads/'+email;

if (!filessystem.existsSync(dir)){
  filessystem.mkdirSync(dir);

}else
{
    console.log("Directory already exist");
}

Comments

2

Just as a newer alternative to Teemu Ikonen's answer, which is very simple and easily readable, is to use the ensureDir method of the fs-extra package.

It can not only be used as a blatant replacement for the built in fs module, but also has a lot of other functionalities in addition to the functionalities of the fs package.

The ensureDir method, as the name suggests, ensures that the directory exists. If the directory structure does not exist, it is created. Like mkdir -p. Not just the end folder, instead the entire path is created if not existing already.

the one provided above is the async version of it. It also has a synchronous method to perform this in the form of the ensureDirSync method.

Comments

0

You can do all of this with the File System module.

const
  fs = require('fs'),
  dirPath = `path/to/dir`

// Check if directory exists.
fs.access(dirPath, fs.constants.F_OK, (err)=>{
  if (err){
    // Create directory if directory does not exist.
    fs.mkdir(dirPath, {recursive:true}, (err)=>{
      if (err) console.log(`Error creating directory: ${err}`)
      else console.log('Directory created successfully.')
    })
  }
  // Directory now exists.
})

You really don't even need to check if the directory exists. The following code also guarantees that the directory either already exists or is created.

const
  fs = require('fs'),
  dirPath = `path/to/dir`

// Create directory if directory does not exist.
fs.mkdir(dirPath, {recursive:true}, (err)=>{
  if (err) console.log(`Error creating directory: ${err}`)
  // Directory now exists.
})

Comments

0

@Liberateur's answer above did not work for me (Node v8.10.0). Little modification did the trick but I am not sure if this is a right way. Please suggest.

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

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

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

Comments

0
const fs = require('fs');

const folderName = '/Users/joe/test';

try {
  if (!fs.existsSync(folderName)) {
    fs.mkdirSync(folderName);
  }
} catch (err) {
  console.error(err);
}

For documentation and more examples, please see here https://nodejs.dev/learn/working-with-folders-in-nodejs

Comments

-1

Raugaral's answer but with -p functionality. Ugly, but it works:

function mkdirp(dir) {
    let dirs = dir.split(/\\/).filter(asdf => !asdf.match(/^\s*$/))
    let fullpath = ''

    // Production directory will begin \\, test is on my local drive.
    if (dirs[0].match(/C:/i)) {
        fullpath = dirs[0] + '\\'
    }
    else {
        fullpath = '\\\\' + dirs[0] + '\\'
    }

    // Start from root directory + 1, build out one level at a time.
    dirs.slice(1).map(asdf => {
        fullpath += asdf + '\\'
        if (!fs.existsSync(fullpath)) {
            fs.mkdirSync(fullpath)
        }
    })
}//mkdirp

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.