如果目录不存在,如何使用 Node.js 创建目录?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21194934/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to create a directory if it doesn't exist using Node.js?
提问by Whisher
Is this the right way to create a directory if it doesn't exist. It should have full permission for the script and readable by others.
如果目录不存在,这是创建目录的正确方法吗?它应该对脚本具有完全权限并且其他人可读。
var dir = __dirname + '/upload';
if (!path.existsSync(dir)) {
fs.mkdirSync(dir, 0744);
}
回答by chovy
var fs = require('fs');
var dir = './tmp';
if (!fs.existsSync(dir)){
fs.mkdirSync(dir);
}
回答by josh3736
No, for multiple reasons.
不,出于多种原因。
The
pathmodule does not have anexists/existsSyncmethod. It is in thefsmodule. (Perhaps you just made a typo in your question?)The docs explicitly discourageyou 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()andfs.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
mkdirand ignoreEEXIST.In general, You should avoid the *
Syncmethods. 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 *
Syncmethods are usuallyfine 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 *
Syncmethods in a server application is in an operation that happens once(and only once), at startup. For example,requireactually usesreadFileSyncto 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.
这些文档明确劝阻您不要使用
exists.fs.exists()是不合时宜的,仅因历史原因而存在。几乎永远不会有理由在您自己的代码中使用它。特别是,在打开文件之前检查文件是否存在是一种反模式,使您容易受到竞争条件的影响:另一个进程可能会在调用
fs.exists()和之间删除文件fs.open()。只需打开文件并在它不存在时处理错误。由于我们谈论的是目录而不是文件,因此该建议意味着您应该无条件地调用
mkdir并忽略EEXIST。通常,您应该避免使用 *
Sync方法。它们是阻塞的,这意味着当您访问磁盘时,您的程序中绝对不会发生任何其他事情。这是一个非常昂贵的操作,它花费的时间打破了节点事件循环的核心假设。*
Sync方法在单一用途的快速脚本中通常很好(那些做一件事然后退出的),但在你编写服务器时几乎不应该使用:你的服务器将无法在整个持续时间内响应任何人的 I/O 请求。如果多个客户端请求需要 I/O 操作,您的服务器将很快停止。我考虑
Sync在服务器应用程序中使用 *方法的唯一时间是在启动时发生一次(并且仅发生一次)的操作中。例如,require实际用于readFileSync加载模块。即便如此,您仍然必须小心,因为大量同步 I/O 会不必要地减慢服务器的启动时间。
相反,您应该使用异步 I/O 方法。
So if we put together those pieces of advice, we get something like this:
所以如果我们把这些建议放在一起,我们会得到这样的东西:
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
});
}
And we can use it like this:
我们可以这样使用它:
ensureExists(__dirname + '/upload', 0744, function(err) {
if (err) // handle folder creation error
else // we're all good
});
Of course, this doesn't account for edge cases like
当然,这不考虑像
- What happens if the folder gets deleted while your program is running? (assuming you only check that it exists once during startup)
- What happens if the folder already exists but with the wrong permissions?
- 如果在您的程序运行时文件夹被删除,会发生什么?(假设您只在启动期间检查它是否存在一次)
- 如果文件夹已经存在但权限错误会怎样?
回答by Toni Gamez
I have found and npm module that works like a charm for this. It's simply do a recursively mkdir when needed, like a "mkdir -p ".
我找到了 npm 模块,它的作用就像一个魅力。它只是在需要时递归地执行 mkdir,例如“mkdir -p”。
回答by bit-less
The mkdirmethod has the ability to recursively createany directories in a path that don't exist, and ignore the ones that do.
该mkdir方法能够在不存在的路径中递归创建任何目录,并忽略存在的目录。
From the Node v10/11 docs:
// Creates /tmp/a/apple, regardless of whether `/tmp` and /tmp/a exist.
fs.mkdir('/tmp/a/apple', { recursive: true }, (err) => {
if (err) throw err;
});
NOTE: You'll need to import the built-in fsmodule first.
注意:您需要先导入内置fs模块。
Now here's a little more robust example that leverages native ES Modules (with flag enabled and .mjs extension), handles non-root paths, and accounts for full pathnames:
现在这里有一个更强大的例子,它利用原生 ES 模块(启用标志和 .mjs 扩展名),处理非根路径,并考虑完整路径名:
import fs from 'fs';
import path from 'path';
createDirectories(pathname) {
const __dirname = path.resolve();
pathname = pathname.replace(/^\.*\/|\/?[^\/]+\.[a-z]+|\/$/g, ''); // Remove leading directory markers, and remove ending /file-name.extension
fs.mkdir(path.resolve(__dirname, pathname), { recursive: true }, e => {
if (e) {
console.error(e);
} else {
console.log('Success');
}
});
}
You can use it like createDirectories('/components/widget/widget.js');.
你可以像createDirectories('/components/widget/widget.js');.
And of course, you'd probably want to get more fancy by using promises with async/await to leverage file creation in a more readable synchronous-looking way when the directories are created; but, that's beyond the question's scope.
当然,您可能希望通过使用带有 async/await 的 promises 来获得更多幻想,以便在创建目录时以更具可读性的同步方式利用文件创建;但是,这超出了问题的范围。
回答by LeOn - Han Li
Just in case any one interested in the one line version. :)
以防万一有人对单行版本感兴趣。:)
//or in typescript: import * as fs from 'fs';
const fs = require('fs');
!fs.existsSync(dir) && fs.mkdirSync(dir);
回答by SamGoody
You can just use mkdirand catch the error if the folder exists.
This is async (so best practice) and safe.
mkdir如果文件夹存在,您可以使用并捕获错误。
这是异步的(所以是最佳实践)和安全的。
fs.mkdir('/path', err => {
if (err && err.code != 'EEXIST') throw 'up'
.. safely do your stuff here
})
(Optionally add a second argument with the mode.)
(可选地为模式添加第二个参数。)
Other thoughts:
其他想法:
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
您可以使用 then 或 await 使用本机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() })您可以制作自己的承诺方法,例如(未经测试):
let mkdirAsync = (path, mode) => new Promise( (resolve, reject) => mkdir (path, mode, err => (err && err.code !== 'EEXIST') ? reject(err) : resolve() ) )对于同步检查,您可以使用:
fs.existsSync(path) || fs.mkdirSync(path)或者你可以使用一个库,最流行的两个是
回答by galki
With the fs-extrapackage you can do this with a one-liner:
使用fs-extra包,您可以使用one-liner执行此操作:
const fs = require('fs-extra');
const dir = '/tmp/this/path/does/not/exist';
fs.ensureDirSync(dir);
回答by Abdul Vajid
The best solution would be to use the npm module called node-fs-extra. It has a method called mkdirwhich creates the directory you mentioned. If you give a long directory path, it will create the parent folders automatically. The module is a super set of npm module fs, so you can use all the functions in fsalso if you add this module.
最好的解决方案是使用名为node-fs-extra的 npm 模块。它有一个方法叫做mkdir创建你提到的目录。如果您提供长目录路径,它将自动创建父文件夹。该模块是 npm 模块的超集fs,因此fs如果添加此模块,您也可以使用其中的所有功能。
回答by Ping.Goblue
var dir = 'path/to/dir';
try {
fs.mkdirSync(dir);
} catch(e) {
if (e.code != 'EEXIST') throw e;
}
回答by Vishnu S Babu
var filessystem = require('fs');
var dir = './path/subpath/';
if (!filessystem.existsSync(dir)){
filessystem.mkdirSync(dir);
}else
{
console.log("Directory already exist");
}
This may help you :)
这可能对你有帮助:)

