Как написать файл, если родительская папка не существует?


мне нужно записать файл по следующему пути:

 fs.writeFile('/folder1/folder2/file.txt', 'content', function () {

 });

но '/folder1/folder2' путь не существует. Поэтому я получаю следующую ошибку:

 message=ENOENT, open /folder1/folder2/file.txt

как я могу написать контент на этот путь?

7 63

7 ответов:

использовать mkdirp в сочетании с path.dirname первый.

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

Если весь путь уже существует,mkdirp является noop. В противном случае он создает все отсутствующие каталоги для вас.

этот модуль делает то, что вы хотите: https://npmjs.org/package/writefile . Получил его, когда гуглил для "writefile mkdirp". Этот модуль возвращает обещание вместо обратного вызова, поэтому не забудьте сначала прочитать введение в обещания. Это может быть на самом деле усложнить вещи для вас.

функция, которую я дал работает в любом случае.

возможно, самое простое, вы можете просто использовать fs-path модуль npm.

ваш код будет выглядеть так:
var fsPath = require('fs-path');

fsPath.writeFile('/folder1/folder2/file.txt', 'content', function(err){
  if(err) {
    throw err;
  } else {
    console.log('wrote a file like DaVinci drew machines');
  }
});

Я считаю, что самый простой способ сделать это-использовать выходной_файл() метод от fs-extra модуль.

почти то же самое, что и writeFile (т. е. он перезаписывает), за исключением того, что если родительский каталог не существует, он создается. варианты - это то, что вы передадите в fs.writeFile ().

пример:

var fs = require('fs-extra');
var file = '/tmp/this/path/does/not/exist/file.txt'

fs.outputFile(file, 'hello!', function (err) {
    console.log(err); // => null

    fs.readFile(file, 'utf8', function (err, data) {
        console.log(data); // => hello!
    });
});

Он также обещана поддержка из коробки в эти дни!.

можно использовать

fs.stat('/folder1/folder2', function(err, stats){ ... });

stats это fs.Stats тип объекта, вы можете проверить stats.isDirectory(). В зависимости от экспертизы err и stats ты можешь что-то сделать, fs.mkdir( ... ) или выдать ошибку.

ссылка

обновление: исправлены запятые в коде.

создать каталоги рекурсивно, если они не существуют! (ноль зависимостей)

const fs = require('fs');
const path = require('path');

function mkDirByPathSync(targetDir, {isRelativeToScript = false} = {}) {
  const sep = path.sep;
  const initDir = path.isAbsolute(targetDir) ? sep : '';
  const baseDir = isRelativeToScript ? __dirname : '.';

  targetDir.split(sep).reduce((parentDir, childDir) => {
    const curDir = path.resolve(baseDir, parentDir, childDir);
    try {
      fs.mkdirSync(curDir);
      console.log(`Directory ${curDir} created!`);
    } catch (err) {
      if (err.code !== 'EEXIST') {
        throw err;
      }

      console.log(`Directory ${curDir} already exists!`);
    }

    return curDir;
  }, initDir);
}

использование

// Default, make directories relative to current working directory.
mkDirByPathSync('path/to/dir');

// Make directories relative to the current script.
mkDirByPathSync('path/to/dir', {isRelativeToScript: true});

// Make directories with an absolute path.
mkDirByPathSync('/path/to/dir');

демо

Попробуйте!

объяснениями

  • это решение обрабатывает как относительные и абсолютное пути. Спасибо @john comment.
  • в случае относительных путей будут созданы целевые каталоги (разрешено) в текущем рабочем каталоге. Чтобы разрешить их относительно текущего скрипта dir, передайте {isRelativeToScript: true}.
  • используя path.sep и path.resolve() не только / конкатенация, чтобы избежать кросс-платформенные вопросы.
  • используя fs.mkdirSync и обработка ошибки с try/catch если брошен для обработки условий гонки: другой процесс может добавить файл между вызовами fs.existsSync() и fs.mkdirSync() и вызывает исключение.
    • другим способом достижения этого может быть проверка наличия файла, а затем его создание, т. е. if (!fs.existsSync(curDir) fs.mkdirSync(curDir);. Но это анти-шаблон, который оставляет код уязвимым для условий гонки. Благодаря комментарию @GershomMaes о проверке существования каталога.
  • требует узел v6 и новее для поддержки деструктурируется. (Если у вас есть проблемы с реализацией этого решения со старыми версиями узлов, просто оставьте мне комментарий)

вот моя пользовательская функция для рекурсивного создания каталогов (без внешних зависимостей):

var fs = require('fs');
var path = require('path');

var myMkdirSync = function(dir){
    if (fs.existsSync(dir)){
        return
    }

    try{
        fs.mkdirSync(dir)
    }catch(err){
        if(err.code == 'ENOENT'){
            myMkdirSync(path.dirname(dir)) //create parent dir
            myMkdirSync(dir) //create dir
        }
    }
}

myMkdirSync(path.dirname(filePath));
var file = fs.createWriteStream(filePath);

вот часть ответа Мирны стол вспыхнула как отдельный ответ:

этот модуль делает то, что вы хотите: https://npmjs.org/package/writefile . Получил его, когда гуглил для "writefile mkdirp". Этот модуль возвращает обещайте вместо того, чтобы принимать обратный вызов, так что не забудьте прочитать некоторые введение в обещания в первую очередь. Это может усложнять для тебя.