How to create full path with node's fs.mkdirSync?

后端 未结 22 1782
故里飘歌
故里飘歌 2020-11-29 18:03

I\'m trying to create a full path if it doesn\'t exist.

The code looks like this:

var fs = require(\'fs\');
if (!fs.existsSync(newDest)) fs.mkdirSync         


        
相关标签:
22条回答
  • 2020-11-29 18:26

    Edit

    NodeJS version 10.12.0 has added a native support for both mkdir and mkdirSync to create a directory recursively with recursive: true option as the following:

    fs.mkdirSync(targetDir, { recursive: true });
    

    And if you prefer fs Promises API, you can write

    fs.promises.mkdir(targetDir, { recursive: true });
    

    Original Answer

    Create directories recursively if they do not exist! (Zero dependencies)

    const fs = require('fs');
    const path = require('path');
    
    function mkDirByPathSync(targetDir, { isRelativeToScript = false } = {}) {
      const sep = path.sep;
      const initDir = path.isAbsolute(targetDir) ? sep : '';
      const baseDir = isRelativeToScript ? __dirname : '.';
    
      return targetDir.split(sep).reduce((parentDir, childDir) => {
        const curDir = path.resolve(baseDir, parentDir, childDir);
        try {
          fs.mkdirSync(curDir);
        } catch (err) {
          if (err.code === 'EEXIST') { // curDir already exists!
            return curDir;
          }
    
          // To avoid `EISDIR` error on Mac and `EACCES`-->`ENOENT` and `EPERM` on Windows.
          if (err.code === 'ENOENT') { // Throw the original parentDir error on curDir `ENOENT` failure.
            throw new Error(`EACCES: permission denied, mkdir '${parentDir}'`);
          }
    
          const caughtErr = ['EACCES', 'EPERM', 'EISDIR'].indexOf(err.code) > -1;
          if (!caughtErr || caughtErr && curDir === path.resolve(targetDir)) {
            throw err; // Throw if it's just the last created dir.
          }
        }
    
        return curDir;
      }, initDir);
    }
    

    Usage

    // Default, make directories relative to current working directory.
    mkDirByPathSync('path/to/dir');
    
    // Make directories relative to the current script.
    mkDirByPathSync('path/to/dir', {isRelativeToScript: true});
    
    // Make directories with an absolute path.
    mkDirByPathSync('/path/to/dir');
    

    Demo

    Try It!

    Explanations

    • [UPDATE] This solution handles platform-specific errors like EISDIR for Mac and EPERM and EACCES for Windows. Thanks to all the reporting comments by @PediT., @JohnQ, @deed02392, @robyoder and @Almenon.
    • This solution handles both relative and absolute paths. Thanks to @john comment.
    • In the case of relative paths, target directories will be created (resolved) in the current working directory. To Resolve them relative to the current script dir, pass {isRelativeToScript: true}.
    • Using path.sep and path.resolve(), not just / concatenation, to avoid cross-platform issues.
    • Using fs.mkdirSync and handling the error with try/catch if thrown to handle race conditions: another process may add the file between the calls to fs.existsSync() and fs.mkdirSync() and causes an exception.
      • The other way to achieve that could be checking if a file exists then creating it, I.e, if (!fs.existsSync(curDir) fs.mkdirSync(curDir);. But this is an anti-pattern that leaves the code vulnerable to race conditions. Thanks to @GershomMaes comment about the directory existence check.
    • Requires Node v6 and newer to support destructuring. (If you have problems implementing this solution with old Node versions, just leave me a comment)
    0 讨论(0)
  • 2020-11-29 18:27

    fs-extra adds file system methods that aren't included in the native fs module. It is a drop in replacement for fs.

    Install fs-extra

    $ npm install --save fs-extra

    const fs = require("fs-extra");
    // Make sure the output directory is there.
    fs.ensureDirSync(newDest);
    

    There are sync and async options.

    https://github.com/jprichardson/node-fs-extra/blob/master/docs/ensureDir.md

    0 讨论(0)
  • 2020-11-29 18:29

    Example for Windows (no extra dependencies and error handling)

    const path = require('path');
    const fs = require('fs');
    
    let dir = "C:\\temp\\dir1\\dir2\\dir3";
    
    function createDirRecursively(dir) {
        if (!fs.existsSync(dir)) {        
            createDirRecursively(path.join(dir, ".."));
            fs.mkdirSync(dir);
        }
    }
    
    createDirRecursively(dir); //creates dir1\dir2\dir3 in C:\temp
    
    0 讨论(0)
  • 2020-11-29 18:29
    const fs = require('fs');
    
    try {
        fs.mkdirSync(path, { recursive: true });
    } catch (error) {
        // this make script keep running, even when folder already exist
        console.log(error);
    }
    
    0 讨论(0)
  • 2020-11-29 18:31

    I had issues with the recursive option of fs.mkdir so I made a function that does the following:

    1. Creates a list of all directories, starting with the final target dir and working up to the root parent.
    2. Creates a new list of needed directories for the mkdir function to work
    3. Makes each directory needed, including the final

      function createDirectoryIfNotExistsRecursive(dirname) {
          return new Promise((resolve, reject) => {
             const fs = require('fs');
      
             var slash = '/';
      
             // backward slashes for windows
             if(require('os').platform() === 'win32') {
                slash = '\\';
             }
             // initialize directories with final directory
             var directories_backwards = [dirname];
             var minimize_dir = dirname;
             while (minimize_dir = minimize_dir.substring(0, minimize_dir.lastIndexOf(slash))) {
                directories_backwards.push(minimize_dir);
             }
      
             var directories_needed = [];
      
             //stop on first directory found
             for(const d in directories_backwards) {
                if(!(fs.existsSync(directories_backwards[d]))) {
                   directories_needed.push(directories_backwards[d]);
                } else {
                   break;
                }
             }
      
             //no directories missing
             if(!directories_needed.length) {
                return resolve();
             }
      
             // make all directories in ascending order
             var directories_forwards = directories_needed.reverse();
      
             for(const d in directories_forwards) {
                fs.mkdirSync(directories_forwards[d]);
             }
      
             return resolve();
          });
       }
      
    0 讨论(0)
  • 2020-11-29 18:32

    Now with NodeJS >= 10.12.0, you can use fs.mkdirSync(path, { recursive: true }) fs.mkdirSync

    0 讨论(0)
提交回复
热议问题