如果目录不存在,以下是创建目录的正确方法吗?
脚本应该拥有完全权限,并可被其他人阅读。
var dir = __dirname + '/upload';
if (!path.existsSync(dir)) {
fs.mkdirSync(dir, 0744);
}
如果目录不存在,以下是创建目录的正确方法吗?
脚本应该拥有完全权限,并可被其他人阅读。
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);
}
或者,对于嵌套目录:
var fs = require('fs');
var dir = './tmp/but/then/nested';
if (!fs.existsSync(dir)){
fs.mkdirSync(dir, { recursive: true });
}
Sync
方法通常是不可取的:不想阻塞事件循环。 - Max Heiber不,由于多种原因。
文档明确禁止使用 exists
。
fs.exists()
是一种过时的存在,仅出于历史原因而存在。在您自己的代码中几乎永远不应该使用它。特别是,在打开文件之前检查文件是否存在是一种反模式,会让您容易受到竞态条件的影响:另一个进程可能会在调用
fs.exists()
和fs.open()
之间删除该文件。只需打开文件并在不存在时处理错误即可。
由于我们讨论的是目录而不是文件,所以这个建议意味着您应该无条件地调用 mkdir
并忽略 EEXIST
。
通常情况下,应避免使用 *Sync
方法。 它们是阻塞的,这意味着在访问磁盘期间您的程序中绝对不能发生任何其他操作。 这是一项非常昂贵的操作,而它所花费的时间打破了 node 的事件循环的核心假设。
*Sync
方法在单一用途的快速脚本(只执行一项任务然后退出)中通常是可以接受的,但是在编写服务器时几乎不应使用:您的服务器将无法响应任何人的 I/O 请求。 如果多个客户端请求需要 I/O 操作,则您的服务器将非常快地停止响应。
我唯一考虑在服务器应用程序中使用 *Sync
方法的时间是在启动时发生 一次(仅一次)的操作。例如,require
实际上使用了 readFileSync
加载模块。
即使如此,您仍然必须小心,因为大量同步 I/O 可能会不必要地减慢服务器的启动时间。
相反,应使用异步 I/O 方法。
因此,如果我们将这些建议综合起来,得到的结果可能如下:
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
});
0744
转换为小数形式,等于 484
。 - josh37360o
而不是仅仅的0
。 请参考https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Deprecated_octal - andreyrdmkdir
方法可以递归创建路径中不存在的任何目录,并忽略已存在的目录。
// Creates /tmp/a/apple, regardless of whether `/tmp` and /tmp/a exist.
fs.mkdir('/tmp/a/apple', { recursive: true }, (err) => {
if (err) throw err;
});
注意:首先需要导入内置的fs
模块。
现在,这里有一个更加健壮的例子,它利用原生的ECMAScript模块(启用标志和.mjs扩展名),处理非根路径,并考虑到完整的路径名:
import fs from 'fs';
import path from 'path';
function 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');
}
});
}
您可以像这样使用 createDirectories('/components/widget/widget.js');
。
当然,如果创建目录时需要使用async/await和Promise来更方便地实现可读性更高的同步方法,但这超出了问题的范围。
/var/log/a/b/c/
,该如何创建?目前它总是抛出错误:Error: EACCES:权限被拒绝,mkdir。 - Mystic我找到了一个 npm模块,它非常适合这个需求。
它会在需要时进行递归的 mkdir
操作,就像执行“mkdir -p”命令一样简单。
简洁版:
// Or in TypeScript: import * as fs from 'fs';
const fs = require('fs');
!fs.existsSync(dir) && fs.mkdirSync(dir);
const fs = require('fs'); !fs.existsSync(dir) && fs.mkdirSync(dir);
(翻译:以上代码是用来检测指定目录是否存在,如果不存在则创建该目录的。) - JackCommonJS
const fs = require('fs');
const path = require('path');
const dir = path.resolve(path.join(__dirname, 'upload');
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
}
// OR
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, {
mode: 0o744, // Not supported on Windows. Default: 0o777
});
}
{
// declare using ECMAScript modules(ESM)
"type": "module",
//...
}
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
// create one custom `__dirname`, because it doesn't exist in es-module env.
// use `import.meta.url` to get the current module's URL,
// then get the module's folder absolute path
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const dir = path.resolve(path.join(__dirname, 'upload');
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
}
// OR
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, {
mode: 0o744, // Not supported on Windows. Default: 0o777
});
}
import { existsSync } from 'node:fs';
NodeJS 版本:v18.2.0
https://nodejs.org/api/fs.html#fsexistssyncpath
https://nodejs.org/api/fs.html#fsmkdirsyncpath-options
https://nodejs.org/api/url.html#urlfileurltopathurl
https://github.com/nodejs/help/issues/2907#issuecomment-757446568
ESM: ECMAScript模块如果文件夹已经存在,你可以直接使用 mkdir
并捕获错误。
这是异步的(最佳实践)和安全的。
fs.mkdir('/path', err => {
if (err && err.code != 'EEXIST') throw 'up'
.. safely do your stuff here
})
(可选)使用第二个参数添加模式。
其他想法:
你可以使用原生的promisify来使用 then 或 await。
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() })
你可以创建自己的 Promise 方法,例如(未经测试):
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)
或者您可以使用一个库,最受欢迎的有两个:
mkdir('/path').catch(err => { if (err.code != 'EEXIST') throw err;}).then(myFunc);
- What Would Be Cool!==
替代 !=
。 - Quentin Roy// import
const fs = require('fs') // In JavaScript
import * as fs from "fs" // in TypeScript
import fs from "fs" // in Typescript
// Use
!fs.existsSync(`./assets/`) && fs.mkdirSync(`./assets/`, { recursive: true })
最好的解决方案是使用npm模块node-fs-extra。它有一个叫做mkdir
的方法,可以创建您提到的目录。如果您提供了一个较长的目录路径,它将自动创建父文件夹。该模块是npm模块fs
的超集,因此如果您添加了这个模块,也可以使用fs
中的所有函数。
TypeError: path.existsSync is not a function
的错误提示(我正在使用 Node v8.10)。 - Jean Paul