Node.jsでファイルに書き込むときにディレクトリを作成する


134

私は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がディレクトリ構造を作成する方法を見つけるのを手伝ってくれる人はいますか?


1
fs.promises.mkdir(path.dirname("tmp/test.txt"), {recursive: true}).then(x => fs.promises.writeFile("tmp/test.txt", "Hey there!"))
Offenso 2018年

回答:


127

ノード> 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 PeresFrançaの回答を参照してください。


4
それは私がやっているものです...それらの統計は私を勝ち取りました。
Aran Mulholland 2014年

ノートfs.promisesはまだ実験的なものであるnodejs.org/dist/latest-v10.x/docs/api/...
lasec0203

132

追加のパッケージを使用したくない場合は、ファイルを作成する前に次の関数を呼び出すことができます。

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

2
これは、stackoverflow.comstatSyncexistsSync
questions / 4482686 /…に

1
path同様に必要なパッケージですfsvar path = require('path')誰かが疑問に思っている場合に備えて。ノードのドキュメントを参照してください。
Rafael Emshoff 2016年


6
関数fs.existsSyncが廃止されているかどうかについて、いくつかの混乱がありました。最初は、私の理解ではそうだと思っていたので、これを反映して回答を更新しました。しかし、現在、@ zzzzBovで指摘されているように、ドキュメントにはfs.existsのみが廃止予定であると明記されており、fs.existsSyncの使用は引き続き有効です。このため、前のコードを削除しましたが、今の答えには(fs.existsSyncを使用した)より単純なソリューションのみが含まれています。
Tiago PeresFrança2016年

1
@chrismarxは、「/ home / documents / a / b / c / myfile.txt」というパスを想像します。「/ home / documents」は存在しますが、その前にあるものはすべて存在しません。「ensureDirectoryExistence」が初めて呼び出されたとき、dirnameは「/ home / documents / a / b / c」です。「/ home / documents / a / b」も存在しないため、現在fs.mkdirSync(dirname)を呼び出すことができません。ディレクトリ「c」を作成するには、まず「/ home / documents / a / b」の存在を確認する必要があります。
Tiago PeresFrança18年

43

ノード-FS-余分あなたは簡単にそれを行うことができます。

インストールする

npm install --save fs-extra

次に、outputFileメソッドを使用します。そのドキュメントは言う:

親ディレクトリが存在しない場合は作成されることを除いて、writeFileとほぼ同じです(つまり、上書きします)。

次の3つの方法で使用できます。

コールバックスタイル

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

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

Promiseの使用

promisesを使用していて、私がそう望んでいる場合、これはコードです:

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

同期バージョン

同期バージョンが必要な場合は、次のコードを使用してください:

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

完全なリファレンスについては、outputFileドキュメントサポートされているすべてのnode-fs-extraメソッドを確認してください。


26

恥知らずなプラグアラート!

必要なパス構造内の各ディレクトリを確認し、存在しない場合は手動で作成する必要があります。これを行うためのすべてのツールは、Nodeのfsモジュールにすでにありますが、私のすべてのmkpathモ​​ジュールで単純にすべて実行できます:https : //github.com/jrajav/mkpath


1
それはファイルを直接作成するのですか、それともディレクトリ構造だけですか?私は、ファイルを作成するときにディレクトリ構造とともにファイルを作成するソリューションを探しています。
Hirvesh、2012年

ディレクトリ構造だけです。最初にmkdir / pathを実行し、エラーがなければ、ファイルの書き込みに進みます。書き込むファイルへのフルパスを指定すると、両方を同時に実行する関数を書くだけで十分です。path.basename
jrajav

1
実際、とても簡単だったので、2分で書きました。:)(未テスト)
jrajav

更新:テストと編集を行いました。初めて動作しない場合は、もう一度お試しください。
jrajav

8
@Kiyura方法は、広く使われているから、この違いmkdirp
David Weldon

9

私はまだコメントできないので、@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);
}

1
これは、@ tiagoのソリューションがファイルパスを期待しているためです。あなたの場合、abcはディレクトリを作成する必要があるファイルとして解釈されます。abcディレクトリも作成するには、パスにダミーファイルを追加しますC:/test/abc/dummy.txt
Sphinxxx 2017

再帰的に使用:fs.promises.mkdir(path.dirname(file), {recursive: true}).then(x => fs.promises.writeFile(file, data))
Offenso

1
@Offensoが最良のソリューションですが、Node.jsバージョン10.12以降のみが対象です。
Nickensoul

8

私のアドバイスは、数行のコードで簡単に実行できる場合は、依存関係に依存しないようにしてください

これが、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);
    });
};

1
3行目はこのようにした方がいいのではないでしょうか。return fs.lstatSync(dpath).isDirectory()それ以外の場合、isDirectory()がfalseを返すとどうなりますか?
Giorgio Aresu 2016年

2
再帰的に使用:fs.promises.mkdir(path.dirname(file), {recursive: true}).then(x => fs.promises.writeFile(file, data))
Offenso

1
@Offensoノード8ではサポートされていません
Ievgen Naida

2

この機能が必要だったので、このモジュールを公開しました。

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

Node.jsのfsメソッドのラッパーのように機能します。あなたはそれをまったく同じ方法を使用することができるようにあなたが希望fs.writeFileしてfs.writeFileSync(非同期および同期書き込みの両方)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.