如果目录不存在,下面的方法是否正确?

它应该对脚本具有完全的权限,并且其他人可以阅读。

var dir = __dirname + '/upload';
if (!path.existsSync(dir)) {
    fs.mkdirSync(dir, 0744);
}

当前回答

适用于v10及以上节点

正如一些回答指出的那样,从节点10开始,您可以对mkdir使用recursive:true

还没有指出的是,当使用recursive:true时,如果目录已经存在,mkdir不会返回错误。

所以你可以这样做:

fsNative.mkdir(dirPath,{recursive:true},(err) => {
    if(err) {
        //note: this does NOT get triggered if the directory already existed
        console.warn(err)
    }
    else{
        //directory now exists 
    }
})

使用承诺

此外,从节点10开始,您可以通过从fs/promises中要求获得所有fs函数的Promise版本

所以把这两件事放在一起,你就得到了这个简单的解决方案:

import * as fs from 'fs/promises';

await fs.mkdir(dirPath, {recursive:true}).catch((err) => {
    //decide what you want to do if this failed
    console.error(err);
});

//directory now exists

其他回答

Use:

var filessystem = require('fs');
var dir = './path/subpath/';

if (!filessystem.existsSync(dir))
{
    filessystem.mkdirSync(dir);
}
else
{
    console.log("Directory already exist");
}

不,原因有很多。

The path module does not have an exists/existsSync method. It is in the fs module. (Perhaps you just made a typo in your question?) The documentation explicitly discourage you from using exists. fs.exists() is an anachronism and exists only for historical reasons. There should almost never be a reason to use it in your own code. In particular, checking if a file exists before opening it is an anti-pattern that leaves you vulnerable to race conditions: another process may remove the file between the calls to fs.exists() and fs.open(). Just open the file and handle the error when it's not there. Since we're talking about a directory rather than a file, this advice implies you should just unconditionally call mkdir and ignore EEXIST. In general, you should avoid the *Sync methods. They're blocking, which means absolutely nothing else in your program can happen while you go to the disk. This is a very expensive operation, and the time it takes breaks the core assumption of node's event loop. The *Sync methods are usually fine in single-purpose quick scripts (those that do one thing and then exit), but should almost never be used when you're writing a server: your server will be unable to respond to anyone for the entire duration of the I/O requests. If multiple client requests require I/O operations, your server will very quickly grind to a halt. The only time I'd consider using *Sync methods in a server application is in an operation that happens once (and only once), at startup. For example, require actually uses readFileSync to load modules. Even then, you still have to be careful because lots of synchronous I/O can unnecessarily slow down your server's startup time. Instead, you should use the asynchronous I/O methods.

所以如果我们把这些建议放在一起,我们会得到这样的结果:

function ensureExists(path, mask, cb) {
    if (typeof mask == 'function') { // Allow the `mask` parameter to be optional
        cb = mask;
        mask = 0o744;
    }
    fs.mkdir(path, mask, function(err) {
        if (err) {
            if (err.code == 'EEXIST') cb(null); // Ignore the error if the folder already exists
            else cb(err); // Something else went wrong
        } else cb(null); // Successfully created folder
    });
}

我们可以这样使用它:

ensureExists(__dirname + '/upload', 0o744, function(err) {
    if (err) // Handle folder creation error
    else // We're all good
});

当然,这并不能解释边缘情况,比如

如果在程序运行时删除文件夹会发生什么?(假设在启动过程中只检查它是否存在一次) 如果文件夹已经存在,但是权限错误,会发生什么?

您可以使用Node.js文件系统命令fs。Stat检查目录是否存在。Mkdir创建一个带有回调的目录,或fs. Mkdir。mkdirSync创建一个没有回调的目录,如下所示:

// First require fs
const fs = require('fs');

// Create directory if not exist (function)
const createDir = (path) => {
    // Check if dir exist
    fs.stat(path, (err, stats) => {
        if (stats.isDirectory()) {
            // Do nothing
        } else {
            // If the given path is not a directory, create a directory
            fs.mkdirSync(path);
        }
    });
};

异步执行此操作的函数(从使用同步函数的SO上的类似答案调整,我现在找不到)

// ensure-directory.js
import { mkdir, access } from 'fs'

/**
 * directoryPath is a path to a directory (no trailing file!)
 */
export default async directoryPath => {
  directoryPath = directoryPath.replace(/\\/g, '/')

  // -- preparation to allow absolute paths as well
  let root = ''
  if (directoryPath[0] === '/') {
    root = '/'
    directoryPath = directoryPath.slice(1)
  } else if (directoryPath[1] === ':') {
    root = directoryPath.slice(0, 3) // c:\
    directoryPath = directoryPath.slice(3)
  }

  // -- create folders all the way down
  const folders = directoryPath.split('/')
  let folderPath = `${root}`
  for (const folder of folders) {
    folderPath = `${folderPath}${folder}/`

    const folderExists = await new Promise(resolve =>
      access(folderPath, error => {
        if (error) {
          resolve(false)
        }
        resolve(true)
      })
    )

    if (!folderExists) {
      await new Promise((resolve, reject) =>
        mkdir(folderPath, error => {
          if (error) {
            reject('Error creating folderPath')
          }
          resolve(folderPath)
        })
      )
    }
  }
}

如果文件夹存在,您可以使用mkdir并捕获错误。 这是异步的(因此是最佳实践)并且安全。

fs.mkdir('/path', err => { 
    if (err && err.code != 'EEXIST') throw 'up'
    .. safely do your stuff here  
    })

(可选地使用mode添加第二个参数。)


其他的想法:

You could use then or await by using native promisify. const util = require('util'), fs = require('fs'); const mkdir = util.promisify(fs.mkdir); var myFunc = () => { ..do something.. } mkdir('/path') .then(myFunc) .catch(err => { if (err.code != 'EEXIST') throw err; myFunc() }) You can make your own promise method, something like (untested): let mkdirAsync = (path, mode) => new Promise( (resolve, reject) => mkdir (path, mode, err => (err && err.code !== 'EEXIST') ? reject(err) : resolve() ) ) For synchronous checking, you can use: fs.existsSync(path) || fs.mkdirSync(path) Or you can use a library, the two most popular being mkdirp (just does folders) fsextra (supersets fs, adds lots of useful stuff)