node.js 如果父文件夹不存在,如何写入文件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16316330/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 14:22:53  来源:igfitidea点击:

How to write file if parent folder doesn't exist?

node.jsfilefile-io

提问by Erik

I need to write file to the following path:

我需要将文件写入以下路径:

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

But '/folder1/folder2'path may not exists. So I get the following error:

'/folder1/folder2'路径可能不存在。所以我收到以下错误:

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

消息=ENOENT,打开/folder1/folder2/file.txt

How can I write content to that path?

如何将内容写入该路径?

回答by Myrne Stol

Use mkdirpin combination with path.dirnamefirst.

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

If the whole path already exists, mkdirpis a noop. Otherwise it creates all missing directories for you.

如果整个路径已经存在,mkdirp则为 noop。否则,它会为您创建所有丢失的目录。

This module does what you want: https://npmjs.org/package/writefile. Got it when googling for "writefile mkdirp". This module returns a promise instead of taking a callback, so be sure to read some introduction to promises first. It might actually complicate things for you.

这个模块做你想做的:https://npmjs.org/package/writefile。在谷歌搜索“writefile mkdirp”时得到了它。这个模块返回一个promise而不是一个回调,所以一定要先阅读一些promise的介绍。它实际上可能会让你的事情复杂化。

The function I gave works in any case.

我给出的函数在任何情况下都有效。

回答by tkarls

I find that the easiest way to do this is to use the outputFile() method from the fs-extramodule.

我发现最简单的方法是使用fs-extra模块中的outputFile() 方法。

Almost the same as writeFile (i.e. it overwrites), except that if the parent directory does not exist, it's created. options are what you'd pass to fs.writeFile().

几乎与 writeFile 相同(即覆盖),除了如果父目录不存在,则创建它。options 是您传递给 fs.writeFile() 的内容。

Example:

例子:

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

It also has promise support out of the box these days!.

这些天它还具有开箱即用的承诺支持!

回答by kevincoleman

Perhaps most simply, you can just use the fs-pathnpm module.

也许最简单的是,您可以只使用fs-pathnpm 模块。

Your code would then look like:

您的代码将如下所示:

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

回答by Mouneer

Edit

编辑

NodeJS version 10 has added a native support for both mkdirand mkdirSyncto create the parent director recursively with recursive: trueoption as the following:

NodeJS 版本 10 添加了对两者的原生支持,mkdirmkdirSync使用recursive: true如下选项递归创建父主管:

fs.mkdirSync(targetDir, { recursive: true });

And if you prefer fs Promises API, you can write

如果你愿意fs Promises API,你可以写

fs.promises.mkdir(targetDir, { recursive: true });

Original Answer

原答案

Create the parent directories recursively if they do not exist! (Zero dependencies)

如果父目录不存在,则递归创建它们!(零依赖

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 : '.';

  return targetDir.split(sep).reduce((parentDir, childDir) => {
    const curDir = path.resolve(baseDir, parentDir, childDir);
    try {
      fs.mkdirSync(curDir);
    } catch (err) {
      if (err.code === 'EEXIST') { // curDir already exists!
        return curDir;
      }

      // To avoid `EISDIR` error on Mac and `EACCES`-->`ENOENT` and `EPERM` on Windows.
      if (err.code === 'ENOENT') { // Throw the original parentDir error on curDir `ENOENT` failure.
        throw new Error(`EACCES: permission denied, mkdir '${parentDir}'`);
      }

      const caughtErr = ['EACCES', 'EPERM', 'EISDIR'].indexOf(err.code) > -1;
      if (!caughtErr || caughtErr && curDir === path.resolve(targetDir)) {
        throw err; // Throw if it's just the last created dir.
      }
    }

    return curDir;
  }, initDir);
}

Usage

用法

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

Demo

演示

Try It!

尝试一下!

Explanations

说明

  • [UPDATE]This solution handles platform-specific errors like EISDIRfor Mac and EPERMand EACCESfor Windows.
  • This solution handles both relativeand absolutepaths.
  • In the case of relative paths, target directories will be created (resolved) in the current working directory. To Resolve them relative to the current script dir, pass {isRelativeToScript: true}.
  • Using path.sepand path.resolve(), not just /concatenation, to avoid cross-platform issues.
  • Using fs.mkdirSyncand handling the error with try/catchif thrown to handle race conditions: another process may add the file between the calls to fs.existsSync()and fs.mkdirSync()and causes an exception.
    • The other way to achieve that could be checking if a file exists then creating it, I.e, if (!fs.existsSync(curDir) fs.mkdirSync(curDir);. But this is an anti-pattern that leaves the code vulnerable to race conditions.
  • Requires Node v6and newer to support destructuring. (If you have problems implementing this solution with old Node versions, just leave me a comment)
  • [更新]该解决方案把手平台特有的错误,如EISDIRMac和EPERMEACCES用于Windows。
  • 此解决方案处理相对路径和绝对路径。
  • 在相对路径的情况下,将在当前工作目录中创建(解析)目标目录。要相对于当前脚本目录解析它们,请传递{isRelativeToScript: true}.
  • 使用path.sepand path.resolve(),而不仅仅是/串联,以避免跨平台问题。
  • 使用fs.mkdirSync和处理错误try/catchif 来处理竞争条件:另一个进程可能会在对fs.existsSync()和的调用之间添加文件fs.mkdirSync()并导致异常。
    • 实现这一目标的另一种方法是检查文件是否存在,然后创建它,即if (!fs.existsSync(curDir) fs.mkdirSync(curDir);. 但这是一种反模式,使代码容易受到竞争条件的影响。
  • 需要Node v6和更新版本来支持解构。(如果您在使用旧 Node 版本实施此解决方案时遇到问题,请给我留言)

回答by MikeD

You can use

您可以使用

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

statsis a fs.Statstype of object, you may check stats.isDirectory(). Depending on the examination of errand statsyou can do something, fs.mkdir( ... )or throw an error.

stats是一种fs.Stats对象,您可以检查stats.isDirectory(). 根据检查结果errstats你可以做些什么,fs.mkdir( ... )或者抛出一个错误。

Reference

参考

Update: Fixed the commas in the code.

更新:修复了代码中的逗号。

回答by math_lab3.ca

Here's my custom function to recursively create directories (with no external dependencies):

这是我递归创建目录的自定义函数(没有外部依赖项):

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

回答by Kailash

Here is my function which works in Node 10.12.0. Hope this will help.

这是我在 Node 10.12.0 中工作的函数。希望这会有所帮助。

const fs = require('fs');
function(dir,filename,content){
        fs.promises.mkdir(dir, { recursive: true }).catch(error => { console.error('caught exception : ', error.message); });
        fs.writeFile(dir+filename, content, function (err) {
            if (err) throw err;
            console.info('file saved!');
        });
    }

回答by Muhammad Numan

With node-fs-extra you can do it easily.

使用 node-fs-extra,您可以轻松完成。

Install it

安装它

npm install --save fs-extra

Then use the outputFilemethod instead of writeFileSync

然后使用outputFile方法而不是writeFileSync

const fs = require('fs-extra');

fs.outputFile('tmp/test.txt', 'Hey there!', err => {
  if(err) {
    console.log(err);
  } else {
    console.log('The file was saved!');
  }
})

回答by Luat Do

let name = "./new_folder/" + file_name + ".png";
await driver.takeScreenshot().then(
  function(image, err) {
    require('mkdirp')(require('path').dirname(name), (err) => {
      require('fs').writeFile(name, image, 'base64', function(err) {
        console.log(err);
      });
    });
  }
);

回答by David Braun

Here's part of Myrne Stol's answer broken out as a separate answer:

以下是 Myrne Stol 的部分答案,作为单独的答案分解:

This module does what you want: https://npmjs.org/package/writefile. Got it when googling for "writefile mkdirp". This module returns a promise instead of taking a callback, so be sure to read some introduction to promises first. It might actually complicate things for you.

这个模块做你想做的:https://npmjs.org/package/writefile。在谷歌搜索“writefile mkdirp”时得到了它。这个模块返回一个promise而不是一个回调,所以一定要先阅读一些promise的介绍。它实际上可能会让你的事情复杂化。