Reputation: 54939
How do I use nodejs to write a file, if the file is in a directory that may or may not exist?
It's kind of similar to this question:
node.js Write file with directories?
Only I need a solution that creates the file while node-fs only makes directories.
Upvotes: 7
Views: 12075
Reputation: 13489
// Create parentDir recursively if it doesn't exist!
const parentDir = 'path/to/parent';
parentDir.split('/').forEach((dir, index, splits) => {
const curParent = splits.slice(0, index).join('/');
const dirPath = path.resolve(curParent, dir);
if (!fs.existsSync(dirPath)) {
fs.mkdirSync(dirPath);
}
});
// Create file.js inside the parentDir
fs.writeFileSync(`${parentDir}/file.js`, 'file Content', 'utf8');
Upvotes: 0
Reputation: 13826
For TypeScript users here's one I just wrote, based on mkdirP:
const _0777 = parseInt('0777', 8);
export function mkdirP(dir: string, opts: {
fs?: {
mkdir: (path: string | Buffer, mode: number,
callback?: (err?: NodeJS.ErrnoException) => void) => void,
stat: (path: string | Buffer,
callback?: (err: NodeJS.ErrnoException,
stats: fs.Stats) => any) => void
}, mode?: number}, f: Function, made?) {
dir = resolve(dir);
if (typeof opts === 'function') {
f = <Function>opts;
opts = {};
}
else if (!opts || typeof opts !== 'object')
opts = {mode: <number>opts};
opts.mode = opts.mode || (_0777 & (~process.umask()));
opts.fs = opts.fs || fs;
if (!made) made = null;
const cb = f || (() => undefined);
opts.fs.mkdir(dir, opts.mode, function (error) {
if (!error) {
made = made || dir;
return cb(null, made);
}
switch (error.code) {
case 'ENOENT':
mkdirP(dirname(dir), opts, function (err, made) {
if (err) cb(err, made);
else mkdirP(dir, opts, cb, made);
});
break;
default:
opts.fs.stat(dir, function (e, stat) {
if (e || !stat.isDirectory()) cb(error || e, made);
else cb(null, made);
});
}
});
}
JavaScript version just remove the type annotations from the signature, i.e.: turn those first few lines to: (dir, opts, mode, f, made) {
.
Upvotes: 0
Reputation: 990
Since fs.exists()
is deprecated, here's another async version using fs.access()
and no external npm modules:
"use strict";
var fs = require('fs');
var path = require('path');
var fileName = '\\tmp\\a\\b\\c\\d.txt'; // e.g. using Windows path separator
var contents = 'any content';
createDirectoryAndFile(fileName, contents);
function createDirectoryAndFile(fileName, contents) {
var dirName = path.dirname(fileName);
var pathAsArray = dirName.split(path.sep);
_createDirectoryAndFile(pathAsArray, '', function() {
fs.open(fileName, 'w+', function(error, data) {
fs.writeFile(fileName, contents, function(error) {});
});
});
}
function _createDirectoryAndFile(pathAsArray, pathSoFar, createFile) {
if (!pathAsArray || pathAsArray.length === 0) {
createFile();
return;
}
var dir = pathAsArray.shift();
pathSoFar = pathSoFar + dir + path.sep;
fs.access(pathSoFar, function(error) {
if (error) { // directory does not exist
fs.mkdir(pathSoFar, function(error) {
if (!error) {
_createDirectoryAndFile(pathAsArray, pathSoFar, createFile);
}
});
} else {
_createDirectoryAndFile(pathAsArray, pathSoFar, createFile);
}
});
}
This of course needs to be improved by adding error handling and supporting permissions.
Upvotes: 0
Reputation: 1
you can use https://github.com/douzi8/file-system
var file = require('file-system');
file.mkdir('1/2/3/4/5', [mode], function(err) {});
Upvotes: -2
Reputation: 11438
I just wrote this as answer to How to write file if parent folder doesn't exist? . Might be useful for someone stumbling upon this in Google:
Use mkdirp in combination with path.dirname
first.
var mkdirp = require("mkdirp")
var fs = require("fs")
var getDirName = require("path").dirname
function writeFile (path, contents, cb) {
mkdirp(getDirName(path), function (err) {
if (err) return cb(err)
fs.writeFile(path, contents, cb)
})
}
Upvotes: 3
Reputation: 18427
From FileUtils:
Modify the functions to satisfy yours needs! But seriously, use a module instead of writing your own!
createDirectory(): Creates a directory. If any of the previous directories that form the path don't exist, they are created. Default permissions: 0777.
File.prototype.createDirectory = function (cb){
if (cb) cb = cb.bind (this);
if (!this._path){
if (cb) cb (NULL_PATH_ERROR, false);
return;
}
if (!canWriteSM (this._usablePath)){
if (cb) cb (SECURITY_WRITE_ERROR, false);
return;
}
var mkdirDeep = function (path, cb){
path.exists (function (exists){
if (exists) return cb (null, false);
FS.mkdir (path.getPath (), function (error){
if (!error) return cb (null, true);
var parent = path.getParentFile ();
if (parent === null) return cb (null, false);
mkdirDeep (parent, function (error, created){
if (created){
FS.mkdir (path.getPath (), function (error){
cb (error, !error);
});
}else{
parent.exists (function (exists){
if (!exists) return cb (null, false);
FS.mkdir (path.getPath (), function (error){
cb (error, !error);
});
});
}
});
});
});
};
mkdirDeep (this.getAbsoluteFile (), function (error, created){
if (cb) cb (error, created);
});
};
createNewFile(): Creates a new file. Default permissions: 0666.
File.prototype.createNewFile = function (cb){
if (cb) cb = cb.bind (this);
if (!this._path){
if (cb) cb (NULL_PATH_ERROR, false);
return;
}
if (!canWriteSM (this._usablePath)){
if (cb) cb (SECURITY_WRITE_ERROR, false);
return;
}
var path = this._usablePath;
PATH.exists (path, function (exists){
if (exists){
if (cb) cb (null, false);
}else{
var s = FS.createWriteStream (path);
s.on ("error", function (error){
if (cb) cb (error, false);
});
s.on ("close", function (){
if (cb) cb (null, true);
});
s.end ();
}
});
};
Upvotes: 6
Reputation: 3259
You can just use something like createWriteStream
.
It will just create the file if it didn't exist.
Upvotes: 0