Node.jsはフォルダーを作成するか、既存のものを使用します


186

私はすでにNode.jsのドキュメントを読んでおり、何かを見落とさない限り、特に特定の操作でパラメーターに何が含まれているかはわかりませんfs.mkdir()。ドキュメントでわかるように、それはそれほどではありません。

現在、私はフォルダーを作成するか、代わりに既存のものを使用しようとするこのコードを持っています:

fs.mkdir(path,function(e){
    if(!e || (e && e.code === 'EEXIST')){
        //do something with contents
    } else {
        //debug
        console.log(e);
    }
});

しかし、これはそれを行う正しい方法ですか?コードをチェックEEXISTすることは、フォルダがすでに存在することを知る正しい方法ですか?fs.stat()ディレクトリを作成する前にできることは知っていますが、それはすでにファイルシステムへの2つのヒットになります。

次に、Node.jsの完全な、または少なくともより詳細なドキュメントで、エラーオブジェクトに含まれる内容、意味するパラメーターなどの詳細が含まれています。


31
小さなnitpickですが、を取り除きe &&ます。場合は!e失敗し、その後、あなたが知っているetruthyです。
私はレイジーが

回答:


236

これを行う良い方法は、mkdirpモジュールを使用することです。

$ npm install mkdirp

ディレクトリを必要とする機能を実行するために使用します。パスが作成された後、またはパスが既に存在する場合は、コールバックが呼び出されます。errmkdirpがディレクトリパスの作成に失敗した場合、エラーが設定されます。

var mkdirp = require('mkdirp');
mkdirp('/tmp/some/path/foo', function(err) { 

    // path exists unless there was an error

});

3
正しい( 'no-dependency-added'を読んだ)答えは、@ Raugaralがを使用して下の方にあるようfs.exists(Sync)です。
Ricardo Pedroni、

@meawoppl、それは 'makedirectory'pです。「p」は不明です。
Andrew

4
@RicardoPedroni正しい方法は、モジュールを使用することです。モジュールは通常、1つの問題を真剣に解決しようと試み、しばしば維持されます。npmで簡単に更新できます。また、fs.exists [Sync]の使用は競合状態を意味するため、使用は特に避けてください。
1j01 2015

16
@ 1j01プラットフォームがネイティブに操作をサポートしている場合、正しい方法がモジュールを使用することだとは思いません。それは混乱への道です。技術的な観点から、より良い答えがあることに同意する必要があります。
C ...

2
@ 1j01また、同期操作の使用はそれらの解決策であるため、同期操作の使用は競合状態を意味します。
C ...

193

編集: この回答は非常に人気があるため、最新のプラクティスを反映するように更新しました。

ノード> = 10

{ recursive: true }Node'sの新しいオプションはfs、これをネイティブに許可します。このオプションは、UNIXの動作を模倣していますmkdir -p。パスのすべての部分が再帰的に存在することを確認し、存在する場合でもエラーをスローしません。

(注:EPERMまたはなどのエラーがスローされる可能性があるEACCESSためtry {} catch (e) {}、実装が影響を受けやすい場合は、aでラップすることをお勧めします。)

同期バージョン。

fs.mkdirSync(dirpath, { recursive: true })

非同期バージョン

await fs.promises.mkdir(dirpath, { recursive: true })

古いノードバージョン

を使用するtry {} catch (err) {}と、競合状態に遭遇することなく、非常に優雅にこれを実現できます。

存在を確認してからディレクトリを作成するまでのデッドタイムを回避するために、単純に作成し、エラーが発生しない場合は無視しますEEXIST(ディレクトリが既に存在する場合)。

エラーがない場合にはEEXIST、しかし、我々は我々のようなものを扱うことが可能性があるため、エラーをスローするべきEPERMEACCES

function ensureDirSync (dirpath) {
  try {
    return fs.mkdirSync(dirpath)
  } catch (err) {
    if (err.code !== 'EEXIST') throw err
  }
}

mkdir -p様再帰的な行動、例えば./a/b/c、あなたがDIRPATHのすべての部分にそれを呼び出す必要があるだろう、例えば./a./a/b.a/b/c


var fs = Npm.require( 'fs'); var dir = process.env.PWD + '/ files / users /' + this.userId + '/'; {fs.mkdirSync(dir);を試してください。} catch(e){if(e.code!= 'EEXIST')throw e; }
アーロン

私はあなたのコードを試して、次のようなカタログ作成を使用するjsスクリプトを作成します:mkdirpSync(path.join(__ dirname、 'first'、 'second'、 'third'、 'ololol'、 'works')); しかし、このエラーが発生しました:$ node 1.js fs.js:747 return binding.mkdir(pathModule._makeLong(path)、^ Error:EPERM、not allowed 'C:\' at Error(native)at Object.fs。 mkdirpSync(C:\ Users \ MAXIM \ Desktop \ test \ 1.js:15:8)のmkdirSync(fs.js:747:18)Object。<anonymous>(C:\ Users \ MAXIM \ Desktop \ test \ 1.js:19:1)...何が問題なのか提案できますか?明らかにWindowsで使用されます:)
Alendorff

EPERMは権限の問題のように思われるため、スクリプトはとにかく実行に
支障をきたす

私はそれが良いだろうと思います:var mkdirpSync = function(dirpath){var parts = dirpath.split(path.sep); for(var i = 1; i <= parts.length; i ++){try {fs.mkdirSync(path.join.apply(null、parts.slice(0、i))); } catch(error){if(error.code!= 'EEXIST'){throw error; }}}}
マニッシュ2015

1
警告:パスが/で始まる場合は機能しません
acemtp

62

汚れがひどいワンライナーが必要な場合は、次のようにします。

fs.existsSync("directory") || fs.mkdirSync("directory");


7
fs.existsSync(...)は非推奨ではないので、この回答は問題ないようです。
Dan Haywood 2017

注意喚起!「dir / foo / bar」では機能しない、つまりmkdir -pフラグ機能がない
Karl Pokus

これには競合状態もあります
Evert

26

node.jsのドキュメントは、fs.mkdir基本的にLinuxのmanページを参照してくださいmkdir(2)。これはEEXIST、パスが存在するが、このルートをたどると厄介なコーナーケースを作成するディレクトリではない場合にも表示されることを示しています。

fs.statパスが存在するかどうか、それが1回の呼び出しでディレクトリであるかどうかを通知する呼び出しの方がよいでしょう。(私が想定していることですが)ディレクトリが既に存在する通常のケースでは、ファイルシステムのヒットは1つだけです。

これらのfsモジュールメソッドはネイティブC APIの薄いラッパーであるため、詳細については、node.jsドキュメントで参照されているマニュアルページを確認する必要があります。


19
statbefore mkdirを呼び出すと、競合状態になる可能性があります。
Roger Lipscombe

24

あなたはこれを使うことができます:

if(!fs.existsSync("directory")){
    fs.mkdirSync("directory", 0766, function(err){
        if(err){
            console.log(err);
            // echo the result back
            response.send("ERROR! Can't make the directory! \n");
        }
    });
}

1
-1。私はこれがうまくstatSyncいくとは信じていません。エンティティがまったく存在しない場合はエラーをスローし、コードをクラッシュさせます。これをtry/catchブロックでラップする必要があります。
クリスフォスター

2
申し訳ありません私が間違っています。「existsSync」の「statSync」を変更
Raugaral

5
nodejs.org/api/fs.html#fs_fs_mkdirsync_path_modeによると、mkdirのSyncバリアントはコールバックを受け入れません
danwellman

1
よるnodejs.org/api/fs.html#fs_fs_existssync_pathfs.existsSync()およびfs.exists()廃止されます。
pau.moreno

7

私はモジュールなしのソリューションを提案します(特に、数行で記述できる小さな関数の場合、累積モジュールは保守性のために推奨されません...):

最後の更新 :

v10.12.0では、NodeJSインプリメント再帰オプション:

// Create recursive folder
fs.mkdir('my/new/folder/create', { recursive: true }, (err) => { if (err) throw err; });

更新:

// Get modules node
const fs   = require('fs');
const path = require('path');

// Create 
function mkdirpath(dirPath)
{
    if(!fs.accessSync(dirPath, fs.constants.R_OK | fs.constants.W_OK))
    {
        try
        {
            fs.mkdirSync(dirPath);
        }
        catch(e)
        {
            mkdirpath(path.dirname(dirPath));
            mkdirpath(dirPath);
        }
    }
}

// Create folder path
mkdirpath('my/new/folder/create');

fs.exists()ノードv9では非推奨です。fs.access()代わりに使用してください。(undefinedファイルが存在する場合は戻ります。それ以外の場合はエラーをスローしますENOENT
chharvey

npmパッケージがなくても機能します。それは貴重なコードです。ありがとう
Karthik Sridharan 2018

これは、既存の長いパスの下にフォルダを作成する場合に非常に適しています;)ありがとうございます。
Tsung Goh

1
どうfs.mkdirSync('my/new/folder/create', {recursive: true})ですか?
saitho

よろしくお願いします!私は他の人を助けるために私の投稿を更新します。ノード10.12.0はあまりにも最近のものでした。
Liberateur


4

これは、ディレクトリを作成するために使用するES6コードです(ディレクトリが存在しない場合)。

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

function createDirectory(directoryPath) {
  const directory = path.normalize(directoryPath);

  return new Promise((resolve, reject) => {
    fs.stat(directory, (error) => {
      if (error) {
        if (error.code === 'ENOENT') {
          fs.mkdir(directory, (error) => {
            if (error) {
              reject(error);
            } else {
              resolve(directory);
            }
          });
        } else {
          reject(error);
        }
      } else {
        resolve(directory);
      }
    });
  });
}

const directoryPath = `${__dirname}/test`;

createDirectory(directoryPath).then((path) => {
  console.log(`Successfully created directory: '${path}'`);
}).catch((error) => {
  console.log(`Problem creating directory: ${error.message}`)
});

注意:

  • 初めにcreateDirectory機能、私は(例えば、これがオンになりますオペレーティングシステムのパス区切り文字タイプは一貫して使用されることを保証するためにパスを正規化C:\directory/testC:\directory\test(Windowsの上にあるとき)
  • fs.exists非推奨です。そのためfs.stat、ディレクトリがすでに存在するかどうかを確認するために使用します
  • ディレクトリが存在しない場合、エラーコードはENOENTE rror NO ENT ry)になります。
  • ディレクトリ自体は、 fs.mkdir
  • 私はfs.mkdirそれをブロックするものよりも非同期関数を好みますfs.mkdirSync、そしてラッピングのためPromise、ディレクトリのパスがディレクトリが正常に作成された後にのみ返されることが保証されます

不要なモジュールを含まないクリーンなソリューションをありがとうございます。それは私には完璧に働きました。このようなより多くの答えがあったらいいのに!
ケン・リヨン

3

私の意見では、JavaScriptでコーディングしている間はファイルシステムのヒット数を数えない方がよいでしょう。しかし、(1) statmkdir(2)mkdirとは、チェック(または廃棄)エラーコードは、両方の方法は、あなたが欲しいものを行うには正しい方法があります。


-1、チェックと破棄のどちらが正しい方法であるかはわかりません。これはほとんど答えではありません。
マットボール

これは、ディレクトリをmkdirするか、既存のディレクトリを使用するための良い方法です。なぜ見えないのか分かりません。エラーコードをチェックすることは丁寧な良いものですが、エラーコードを破棄することは単に良いものです。同意しない?
Chul-Woong Yang

1
これは言語の壁の問題かもしれませんが、私はこれを、OPが求めている質問に答えないだけとして読んでいます。
マットボール

あなたの言いたいことがわかります。しかし、私は物事を正しく行うには多くの方法があると信じています。ありがとう。
Chul-Woong Yang

2

ユーザーごとに動的な名前のディレクトリを作成します...このコードを使用します

***suppose email contain user mail address***

var filessystem = require('fs');
var dir = './public/uploads/'+email;

if (!filessystem.existsSync(dir)){
  filessystem.mkdirSync(dir);

}else
{
    console.log("Directory already exist");
}

1

これらはすべてファイルシステムモジュールで実行できます。

const
  fs = require('fs'),
  dirPath = `path/to/dir`

// Check if directory exists.
fs.access(dirPath, fs.constants.F_OK, (err)=>{
  if (err){
    // Create directory if directory does not exist.
    fs.mkdir(dirPath, {recursive:true}, (err)=>{
      if (err) console.log(`Error creating directory: ${err}`)
      else console.log('Directory created successfully.')
    })
  }
  // Directory now exists.
})

ディレクトリが存在するかどうかを確認する必要すらありません。次のコードは、ディレクトリがすでに存在するか作成されることも保証します。

const
  fs = require('fs'),
  dirPath = `path/to/dir`

// Create directory if directory does not exist.
fs.mkdir(dirPath, {recursive:true}, (err)=>{
  if (err) console.log(`Error creating directory: ${err}`)
  // Directory now exists.
})

0

ラウガラルの答えですが、-p機能があります。醜いですが、うまくいきます:

function mkdirp(dir) {
    let dirs = dir.split(/\\/).filter(asdf => !asdf.match(/^\s*$/))
    let fullpath = ''

    // Production directory will begin \\, test is on my local drive.
    if (dirs[0].match(/C:/i)) {
        fullpath = dirs[0] + '\\'
    }
    else {
        fullpath = '\\\\' + dirs[0] + '\\'
    }

    // Start from root directory + 1, build out one level at a time.
    dirs.slice(1).map(asdf => {
        fullpath += asdf + '\\'
        if (!fs.existsSync(fullpath)) {
            fs.mkdirSync(fullpath)
        }
    })
}//mkdirp

0

非常にシンプルで読みやすいTeemu Ikonenの回答の新しい代替案と同じようensureDirに、fs-extraパッケージのメソッドを使用します。

ビルトインfsモジュールのあからさまな代替品として使用できるだけでなく、fsパッケージの機能に加えて他の多くの機能も備えています。

このensureDirメソッドは、名前が示すように、ディレクトリが存在することを保証します。ディレクトリ構造が存在しない場合は作成されます。のようにmkdir -p。終了フォルダだけでなく、パスがまだ存在しない場合は、パス全体が作成されます。

上記のasyncバージョンはそのバージョンです。また、これをメソッドの形式で実行する同期メソッドもありensureDirSyncます。


0

上記の @Liberateur の答えは私には機能しませんでした(Node v8.10.0)。少し変更を加えただけでうまくいきましたが、これが正しい方法かどうかはわかりません。提案してください。

// Get modules node
const fs   = require('fs');
const path = require('path');

// Create
function mkdirpath(dirPath)
{
    try {
        fs.accessSync(dirPath, fs.constants.R_OK | fs.constants.W_OK);
    }
    catch(err) {
        try
        {
            fs.mkdirSync(dirPath);
        }
        catch(e)
        {
            mkdirpath(path.dirname(dirPath));
            mkdirpath(dirPath);
        }
    }
}

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