201

我一直在修补 Node.js,发现了一个小问题。我有一个脚本,它位于一个名为data. 我希望脚本将一些数据写入子目录中子目录中的文件data。但是我收到以下错误:

{ [Error: ENOENT, open 'D:\data\tmp\test.txt'] errno: 34, code: 'ENOENT', path: 'D:\\data\\tmp\\test.txt' }

代码如下:

var fs = require('fs');
fs.writeFile("tmp/test.txt", "Hey there!", function(err) {
    if(err) {
        console.log(err);
    } else {
        console.log("The file was saved!");
    }
}); 

如果 Node.js 不退出以写入文件,任何人都可以帮助我找出如何让 Node.js 创建目录结构吗?

4

8 回答 8

208

节点 > 10.12.0

fs.mkdir现在接受{ recursive: true }如下选项:

// Creates /tmp/a/apple, regardless of whether `/tmp` and /tmp/a exist.
fs.mkdir('/tmp/a/apple', { recursive: true }, (err) => {
  if (err) throw err;
});

或承诺:

fs.promises.mkdir('/tmp/a/apple', { recursive: true }).catch(console.error);

节点 <= 10.11.0

您可以使用mkdirpfs-extra之类的软件包解决此问题。如果您不想安装软件包,请参阅下面的 Tiago Peres França 的回答。

于 2012-11-24T18:54:26.743 回答
167

如果您不想使用任何额外的包,您可以在创建文件之前调用以下函数:

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

function ensureDirectoryExistence(filePath) {
  var dirname = path.dirname(filePath);
  if (fs.existsSync(dirname)) {
    return true;
  }
  ensureDirectoryExistence(dirname);
  fs.mkdirSync(dirname);
}
于 2015-12-29T11:04:00.690 回答
61

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

安装它

npm install --save fs-extra

然后使用outputFile方法。它的文档说:

几乎与writeFile(即覆盖)相同,除了如果父目录不存在,则创建它。

您可以通过四种方式使用它。

异步/等待

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

await fse.outputFile('tmp/test.txt', 'Hey there!');

使用承诺

如果你使用promises,代码如下:

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

fse.outputFile('tmp/test.txt', 'Hey there!')
   .then(() => {
       console.log('The file has been saved!');
   })
   .catch(err => {
       console.error(err)
   });

回调样式

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

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

同步版本

如果您想要同步版本,只需使用以下代码:

const fse = require('fs-extra')

fse.outputFileSync('tmp/test.txt', 'Hey there!')

如需完整参考,请查看outputFile文档和所有node-fs-extra 支持的方法

于 2017-08-02T16:09:41.047 回答
27

无耻的插头警报!

您必须检查所需路径结构中的每个目录,如果不存在则手动创建它。所有这样做的工具都已经在 Node 的 fs 模块中了,但是你可以简单地使用我的 mkpath 模块来完成所有这些:https ://github.com/jrajav/mkpath

于 2012-11-24T15:35:58.723 回答
10

由于我还不能发表评论,因此我发布了基于@tiago-peres-frança 出色解决方案的增强答案(谢谢!)。在路径中仅缺少最后一个目录的情况下,他的代码不会创建目录,例如输入是“C:/test/abc”并且“C:/test”已经存在。这是一个有效的片段:

function mkdirp(filepath) {
    var dirname = path.dirname(filepath);

    if (!fs.existsSync(dirname)) {
        mkdirp(dirname);
    }

    fs.mkdirSync(filepath);
}
于 2016-12-06T10:52:37.560 回答
9

我的建议是:当你可以用几行代码轻松完成时,尽量不要依赖依赖项

以下是您试图在14行代码中实现的目标:

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);
    });
};
于 2016-11-02T17:02:41.687 回答
5

与上述相同的答案,但async await已准备好使用!

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

例子:

(async () {
  const data = 'Hello, World!';
  await writeFile('dist/posts/hello-world.html', data);
})();
于 2021-01-07T15:52:51.493 回答
2

我刚刚发布了这个模块,因为我需要这个功能。

https://www.npmjs.org/package/filendir

它就像 Node.js fs 方法的包装器一样工作。因此,您可以像使用fs.writeFileand一样使用它fs.writeFileSync(异步和同步写入)

于 2014-05-10T10:19:48.820 回答