😎

[メモ]node.js filesystemを使用したファイル生成時に、再帰的に親ディレクトリを作成する。

2021/05/14に公開

メモ書きです。

やりたいこと

fs.writeFileを使用したファイル生成時にディレクトリ階層まで作成する。

mkdirpなどのライブラリなどを使用してもいいですが、これだけのために何か入れるのも面倒なので、fsで使える関数だけでなんとかしたいなと思った。

とりあえず作ってみた

const outputDirPath = __dirname + "./.output";

export const createFile = (data, filename) => {
  fs.writeFile(outputDirPath + filename, data, (err) => {
    if (err) throw err;
};

writeFile関数を使用してファイルを作ります。
この時にfilenameに/dir1/dir2/file.txtを渡して実行してみます。

createFile("test dayo", "dir1/dir2/file.txt");

するとエラーが発生します。

Error: ENOENT: no such file or directory, open '/Users/yoshimok/hoge/src/./output/dir1/dir2/file.txt'

./output/dir1/dir2/が存在しないため、ファイルを作成することができないらしいです。
そのため先にディレクトリを用意してあげる必要があります。

fsの関数の中にディレクトリを作成する関数mkdir()があるためそれを使えば良さそうです。

またこちらの関数ではoptionに再帰的にいい感じに作成してくれるように設定できるようなので、そちらを設定してあげます。 Node v10.12.0以降で使用できるらしいです。

fs.mkdir(outputDirPath + additionalDir, { recursive: true }, (err) => {
  if (err) throw err;
});

これを使用してcreateFile関数を修正してみました。

const outputDirPath = __dirname + "./.output";

export const createFile = (data, filename) => {
  const filePath = outputDirPath + filename;

  fs.writeFile(filePath, data, (err) => {
    // ディレクトリ作成できなかったとき
    if (err && err.code === "ENOENT") {
      // ディレクトリ部分だけ切り取り
      const dir = filePath.substring(0, filePath.lastIndexOf("/"));

      // 親ディレクトリ作成
      fs.mkdir(dir, { recursive: true }, (err) => {
        if (err) throw err;
        createFile(data, filename);
      });
      return;
    }
    console.log("created");
  });
};

実行してみましたが問題なく動きました。やったね!

おわりに

急ぎで雑に書いてしまったけど、もっと綺麗に書けそう。ていうかオプションでfile作成時にも再帰的にディレクトリまで作ってくれたりしないもんですかね。(するとファイルの作成じゃなくなるじゃん!ってなるか)

とりあえずやりたいことはできたのでよかったです。

参考

https://nodejs.org/api/fs.html#fs_filehandle_writefile_data_options
https://nodejs.org/docs/latest-v10.x/api/fs.html#fs_fs_mkdir_path_options_callback

Discussion