节点如何创build一个目录如果不存在?

这是创build一个不存在的目录的正确方法。 它应该有脚本的完全许可和其他人可读。

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

不,由于多种原因。

  1. path模块没有exists / existsSync方法。 它在fs模块中。 (也许你只是在你的问题上犯了一个错字?)

  2. 该文件显然不鼓励你使用exists

    fs.exists()是一个时代错误,只存在于历史原因。 几乎从来没有理由在你自己的代码中使用它。

    特别是,在打开文件之前检查文件是否存在是一种反模式,使您容易受到竞争状况的影响:另一个进程可能会在调用fs.exists()fs.open()之间删除文件。 只要打开文件并在不存在的情况下处理错误。

    由于我们正在讨论一个目录而不是文件,这个build议意味着你应该无条件地调用mkdir并忽略EEXIST

  3. 一般来说,你应该避免* Sync方法。 他们阻止,这意味着当你去到磁盘时,你的程序中绝对没有别的东西可以发生。 这是一个非常昂贵的操作,所花费的时间打破了节点事件循环的核心假设。

    * Sync方法通常在单一用途的快速脚本(那些只做一件事然后退出的脚本)中很好,但在编写服务器时几乎不会被使用:服务器将无法响应任何人I / O请求的持续时间。 如果多个客户端请求需要I / O操作,您的服务器将会很快停止。


    我唯一考虑在服务器应用程序中使用* Sync方法是在启动时只发生一次 (且只发生一次)的操作。 例如, require 实际上使用readFileSync来加载模块。

    即使如此,仍然要小心,因为许多同步I / O可能会不必要地减慢服务器的启动时间。


    相反,您应该使用asynchronousI / O方法。

所以如果我们把这些build议放在一起,我们得到这样的东西:

 function ensureExists(path, mask, cb) { if (typeof mask == 'function') { // allow the `mask` parameter to be optional cb = mask; mask = 0777; } 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', 0744, function(err) { if (err) // handle folder creation error else // we're all good }); 

当然,这不包括像边缘情况

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

我发现和npm模块就像这样的魅力。 只需要做一个recursion的mkdir,就像“mkdir -p”一样。

https://www.npmjs.com/package/mkdirp

最好的解决scheme是使用名为node-fs-extra的npm模块。 它有一个名为mkdir的方法,它创build你提到的目录。 如果你给一个长的目录path,它会自动创build父文件夹。 该模块是npm模块fs的超级集合,所以如果添加此模块,则可以使用fs所有函数。

我想给josh3736的答案添加一个Typescript Promise重构。

它做同样的事情,并具有相同的边缘情况下,它恰好使用承诺,typescript typedefs和“严格使用”的作品。

 // https://en.wikipedia.org/wiki/File_system_permissions#Numeric_notation const allRWEPermissions = parseInt("0777", 8); function ensureFilePathExists(path: string, mask: number = allRWEPermissions): Promise<void> { return new Promise<void>( function(resolve: (value?: void | PromiseLike<void>) => void, reject: (reason?: any) => void): void{ mkdir(path, mask, function(err: NodeJS.ErrnoException): void { if (err) { if (err.code === "EEXIST") { resolve(null); // ignore the error if the folder already exists } else { reject(err); // something else went wrong } } else { resolve(null); // successfully created folder } }); }); } 
  var filessystem = require('fs'); var dir = './path/subpath/'; if (!filessystem.existsSync(dir)){ filessystem.mkdirSync(dir); }else { console.log("Directory already exist"); } 

这可能会帮助你:)

 var dir = 'path/to/dir'; try { fs.mkdirSync(dir); } catch(e) { if (e.code ~= 'EEXIST') throw e; } 

这里是一个小函数来recursion创build目录:

 const createDir = (dir) => { // This will create a dir given a path such as './folder/subfolder' const splitPath = dir.split('/'); splitPath.reduce((path, subPath) => { let currentPath; if(subPath != '.'){ currentPath = path + '/' + subPath; if (!fs.existsSync(currentPath)){ fs.mkdirSync(currentPath); } } else{ currentPath = subPath; } return currentPath }, '') }