我一直在修补Node.js并发现了一个小问题。我有一个脚本驻留在名为data
的目录中。我希望脚本将一些数据写入data
子目录中的子目录中的文件。但是我收到以下错误:
{ [Error: ENOENT, open 'D:\data\tmp\test.txt'] errno: 34, code: 'ENOENT', path: 'D:\\data\\tmp\\test.txt' }
代码如下:
var fs = require('fs');
fs.writeFile("tmp/test.txt", "Hey there!", function(err) {
if(err) {
console.log(err);
} else {
console.log("The file was saved!");
}
});
有人可以帮我找出如果Node.js没有退出写入文件的话会如何创建目录结构吗?
答案 0 :(得分:104)
如果您不想使用任何其他套餐,可以在创建文件之前调用以下函数:
var path = require('path'),
fs = require('fs');
function ensureDirectoryExistence(filePath) {
var dirname = path.dirname(filePath);
if (fs.existsSync(dirname)) {
return true;
}
ensureDirectoryExistence(dirname);
fs.mkdirSync(dirname);
}
答案 1 :(得分:81)
fs.mkdir现在接受{ recursive: true }
选项,如下所示:
// 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.promises.mkdir('/tmp/a/apple', { recursive: true }).catch(console.error);
您可以使用mkdirp或fs-extra这样的包解决此问题。如果您不想安装软件包,请参阅下面的TiagoPeresFrança的答案。
答案 2 :(得分:28)
使用node-fs-extra,您可以轻松完成。
npm install --save fs-extra
然后使用outputFile
方法。它的文件说:
与writeFile几乎相同(即它覆盖),除非是 父目录不存在,它已创建。
您可以通过三种方式使用它:
const fse = require('fs-extra');
fse.outputFile('tmp/test.txt', 'Hey there!', err => {
if(err) {
console.log(err);
} else {
console.log('The file was saved!');
}
})
如果你使用promises,我希望如此,这就是代码:
fse.outputFile('tmp/test.txt', 'Hey there!')
.then(() => {
console.log('The file was saved!');
})
.catch(err => {
console.error(err)
});
如果您想要同步版本,请使用以下代码:
fse.outputFileSync('tmp/test.txt', 'Hey there!')
要获得完整参考,请查看outputFile
documentation和所有node-fs-extra supported methods。
答案 3 :(得分:26)
无耻插头警报!
您必须检查所需路径结构中的每个目录,如果它不存在,则手动创建。所有这样做的工具都已经存在于Node的fs模块中,但你可以使用我的mkpath模块完成所有这些工作:https://github.com/jrajav/mkpath
答案 4 :(得分:9)
由于我还没有评论,我发布了一个基于@ tiago-peres-frança梦幻般解决方案的增强答案(谢谢!)。他的代码在路径中只缺少最后一个目录的情况下不会创建目录,例如输入为“C:/ test / abc”,“C:/ test”已存在。这是一个有效的代码片段:
function mkdirp(filepath) {
var dirname = path.dirname(filepath);
if (!fs.existsSync(dirname)) {
mkdirp(dirname);
}
fs.mkdirSync(filepath);
}
答案 5 :(得分:8)
我的建议是:尽量使用几行代码轻松完成依赖
以下是您在 14 代码行中尝试实现的目标:
fs.isDir = function(dpath) {
try {
return fs.lstatSync(dpath).isDirectory();
} catch(e) {
return false;
}
};
fs.mkdirp = function(dirname) {
dirname = path.normalize(dirname).split(path.sep);
dirname.forEach((sdir,index)=>{
var pathInQuestion = dirname.slice(0,index+1).join(path.sep);
if((!fs.isDir(pathInQuestion)) && pathInQuestion) fs.mkdirSync(pathInQuestion);
});
};
答案 6 :(得分:3)
我刚刚发布了这个模块,因为我需要这个功能。
https://www.npmjs.org/package/filendir
它的工作方式类似于Node.js fs方法的包装器。因此,您可以使用与fs.writeFile
和fs.writeFileSync
完全相同的方式(同步和同步写入)
答案 7 :(得分:1)
相同的答案同上,但使用async await
,并准备使用!
const fs = require('fs/promises');
const path = require('path');
async function isExists(path) {
try {
await fs.access(path);
return true;
} catch {
return false;
}
};
async function writeFile(filePath, data) {
try {
const dirname = path.dirname(filePath);
const exist = await isExists(dirname);
if (!exist) {
await fs.mkdir(dirname, {recursive: true});
}
await fs.writeFile(filePath, data, 'utf8');
} catch (err) {
throw new Error(err);
}
}
示例:
(async () {
const data = 'Hello, World!';
await writeFile('dist/posts/hello-world.html', data);
})();
答案 8 :(得分:0)
首先获取包括目录的完整路径,然后提取目录
//Just for the sake of example
cwd=process.cwd()
filendir=path.resolve(cwd,'_site/assets/text','node.txt')
// Extracting directory name
mkdir=path.dirname(filendir)
现在创建目录,添加递归选项:true,如@David Weldon所述
fs.mkdirSync(mkdir,{recursive:true})
然后创建文件
data='Some random text'
fs.writeFileSync(filendir,data)