I\'ve been tinkering with Node.js and found a little problem. I\'ve got a script which resides in a directory called data
. I want the script to write some data to
With node-fs-extra you can do it easily.
npm install --save fs-extra
Then use the outputFile
method. Its documentation says:
Almost the same as writeFile (i.e. it overwrites), except that if the parent directory does not exist, it's created.
You can use it in three ways:
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!');
}
})
If you use promises, and I hope so, this is the code:
fse.outputFile('tmp/test.txt', 'Hey there!')
.then(() => {
console.log('The file was saved!');
})
.catch(err => {
console.error(err)
});
If you want a sync version, just use this code:
fse.outputFileSync('tmp/test.txt', 'Hey there!')
For a complete reference, check the outputFile documentation and all node-fs-extra supported methods.
Since I cannot comment yet, I'm posting an enhanced answer based on @tiago-peres-frança fantastic solution (thanks!). His code does not make directory in a case where only the last directory is missing in the path, e.g. the input is "C:/test/abc" and "C:/test" already exists. Here is a snippet that works:
function mkdirp(filepath) {
var dirname = path.dirname(filepath);
if (!fs.existsSync(dirname)) {
mkdirp(dirname);
}
fs.mkdirSync(filepath);
}
I just published this module because I needed this functionality.
https://www.npmjs.org/package/filendir
It works like a wrapper around Node.js fs methods. So you can use it exactly the same way you would with fs.writeFile
and fs.writeFileSync
(both async and synchronous writes)
fs.mkdir now accepts a { recursive: true }
option like so:
// Creates /tmp/a/apple, regardless of whether `/tmp` and /tmp/a exist.
fs.mkdir('/tmp/a/apple', { recursive: true }, (err) => {
if (err) throw err;
});
or with a promise:
fs.promises.mkdir('/tmp/a/apple', { recursive: true }).catch(console.error);
You can solve this with a package like mkdirp or fs-extra. If you don't want to install a package, please see Tiago Peres França's answer below.
Same answer as above, but with async await
and ready to use!
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);
}
}
Example:
(async () {
const data = 'Hello, World!';
await writeFile('dist/posts/hello-world.html', data);
})();
My advise is: try not to rely on dependencies when you can easily do it with few lines of codes
Here's what you're trying to achieve in 14 lines of code:
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);
});
};