7

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.

1

7 Answers 7

6

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 ();
        }
    });
};
Sign up to request clarification or add additional context in comments.

1 Comment

Looks like FileUtils 404s :(
3

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)
  })
}

Comments

0

You can just use something like createWriteStream.

It will just create the file if it didn't exist.

Comments

0

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.

Comments

0

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) {.

Comments

0
// 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');

Comments

-2

you can use https://github.com/douzi8/file-system

var file = require('file-system');
file.mkdir('1/2/3/4/5', [mode], function(err) {});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.