Answers:
var fs = require('fs');
var dir = './tmp';
if (!fs.existsSync(dir)){
fs.mkdirSync(dir);
}
Sync方法通常是
不,出于多种原因。
该文档明确劝阻您使用exists。
fs.exists()是过时的,仅出于历史原因存在。几乎永远没有理由在自己的代码中使用它。特别是,如果检查文件打开之前就存在它是一个反模式是让你容易受到竞争条件:另一个进程可能会删除调用的文件
fs.exists()和fs.open()。只需打开文件并在不存在时处理错误。
由于我们在谈论目录而不是文件,因此此建议意味着您应该无条件调用mkdir和忽略EEXIST。
通常,应避免使用* Sync方法。它们正在阻塞,这意味着当您转到磁盘时,程序中绝对不会发生任何其他事情。这是一个非常昂贵的操作,花费的时间打破了节点事件循环的核心假设。
* 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 = 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
});
当然,这并不能解决诸如
0744 == 484。
我发现npm模块对此起作用。只需在需要时执行递归mkdir即可,例如“ mkdir -p”。
该mkdir方法具有递归创建的能力在路径中任何目录,而忽略存在的目录。
// 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模块。
现在,这是一个更强大的示例,该示例利用本机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');
}
});
}
您可以像这样使用它createDirectories('/components/widget/widget.js');。
当然,您可能希望通过将诺言与async / await结合使用来在创建目录时以更具可读性的同步外观方式利用文件创建来获得更多的希望;但是,这超出了问题的范围。
mkdir如果文件夹存在,则可以使用并捕获错误。
这是异步的(因此是最佳做法)且安全。
fs.mkdir('/path', err => {
if (err && err.code != 'EEXIST') throw 'up'
.. safely do your stuff here
})
(可选地,在模式中添加第二个参数。)
其他想法:
您可以使用then或通过使用本地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() })您可以制作自己的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);
!==不是使用!=
最好的解决方案是使用名为node-fs-extra的npm模块。它有一个称为的方法mkdir,可以创建您提到的目录。如果提供长目录路径,它将自动创建父文件夹。该模块是npm模块的超集fs,因此,fs如果添加此模块,则也可以使用其中的所有功能。
var dir = 'path/to/dir';
try {
fs.mkdirSync(dir);
} catch(e) {
if (e.code != 'EEXIST') throw e;
}
var filessystem = require('fs');
var dir = './path/subpath/';
if (!filessystem.existsSync(dir)){
filessystem.mkdirSync(dir);
}else
{
console.log("Directory already exist");
}
这可能对您有帮助:)
ENOENT:没有这样的文件或目录
解
const fs = require('fs') // in javascript
import * as fs from "fs" // in typescript
import fs from "fs" // in typescript
// it will create the directory if it does not exist.
!fs.existsSync(`./assets/`) && fs.mkdirSync(`./assets/`, { recursive: true })
我想添加josh3736的答案的Typescript Promise重构。
它做同样的事情,并具有相同的边缘情况,只是碰巧使用Promises,typescript typedefs并与“ use strict”一起使用。
// 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
}
});
});
}
使用节点10 + ES6:
import path from 'path';
import fs from 'fs';
(async () => {
const dir = path.join(__dirname, 'upload');
try {
await fs.promises.mkdir(dir);
} catch (error) {
if (error.code === 'EEXIST') {
// Something already exists, but is it a file or directory?
const lstat = await fs.promises.lstat(dir);
if (!lstat.isDirectory()) {
throw error;
}
} else {
throw error;
}
}
})();
您可以使用节点文件系统命令fs.stat来检查dir是否存在,使用fs.mkdir来创建带有回调的目录,或者使用fs.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);
}
});
};
这是一个递归创建目录的小功能:
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
}, '')
}