回答:
var fs = require('fs');
var dir = './tmp';
if (!fs.existsSync(dir)){
fs.mkdirSync(dir);
}
Syncメソッドの使用は、通常、
いいえ、いくつかの理由があります。
pathモジュールはありませんexists/ existsSyncメソッドを。fsモジュール内にあります。(おそらくあなたはあなたの質問にタイプミスをしただけですか?)
ドキュメントでは、の使用を明示的に推奨していませんexists。
fs.exists()時代錯誤であり、歴史的な理由でのみ存在します。独自のコードで使用する理由はほとんどありません。特に、開く前にファイルが存在するかどうかを確認することは、競合状態に対して脆弱なままになるアンチパターンです。別のプロセスが
fs.exists()との呼び出しの間にファイルを削除する可能性がありますfs.open()。ファイルを開いて、そこにないときにエラーを処理するだけです。
ファイルではなくディレクトリについて話しているので、このアドバイスは無条件にを呼び出しmkdirて無視する必要があることを意味しますEEXIST。
一般に、* Syncメソッドは使用しないでください。それらはブロックしているので、ディスクにアクセスしている間、プログラム内で他に何も起こり得ません。これは非常にコストのかかる操作であり、かかる時間はノードのイベントループの中心的な前提を破ります。
* Syncメソッドは通常、単一目的のクイックスクリプト(1つの処理を行ってから終了するスクリプト)では問題ありませんが、サーバーを作成しているときにはほとんど使用しないでください。入出力要求の。複数のクライアント要求がI / O操作を必要とする場合、サーバーはすぐに停止します。
Syncサーバーアプリケーションで* メソッドの使用を検討するのは、起動時に1 回(そして1回だけ)発生する操作だけです。たとえば、require 実際にを使用readFileSyncしてモジュールをロードします。
それでも、多くの同期I / Oがサーバーの起動時間を不必要に遅くする可能性があるため、注意が必要です。
代わりに、非同期I / Oメソッドを使用する必要があります。
したがって、これらのアドバイスをまとめると、次のような結果になります。
function ensureExists(path, mask, cb) {
if (typeof mask == 'function') { // allow the `mask` parameter to be optional
cb = mask;
mask = 0777;
}
fs.mkdir(path, mask, function(err) {
if (err) {
if (err.code == 'EEXIST') cb(null); // ignore the error if the folder already exists
else cb(err); // something else went wrong
} else cb(null); // successfully created folder
});
}
そして、次のように使用できます。
ensureExists(__dirname + '/upload', 0744, function(err) {
if (err) // handle folder creation error
else // we're all good
});
もちろん、これは次のようなエッジケースを考慮していません
0744 == 484。
私はこれの魅力のように機能するnpmモジュールを見つけました。「mkdir -p」のように、必要に応じてmkdirを再帰的に実行するだけです。
このmkdirメソッドには、存在しないパスにディレクトリを再帰的に作成し、存在するディレクトリを無視する機能があります。
// 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最初に組み込みモジュールをインポートする必要があります。
次に、ネイティブESモジュール(フラグが有効で.mjs拡張子が付いている)を活用し、非ルートパスを処理し、完全パス名を説明する、もう少し堅牢な例を示します。
import fs from 'fs';
import path from 'path';
createDirectories(pathname) {
const __dirname = path.resolve();
pathname = pathname.replace(/^\.*\/|\/?[^\/]+\.[a-z]+|\/$/g, ''); // Remove leading directory markers, and remove ending /file-name.extension
fs.mkdir(path.resolve(__dirname, pathname), { recursive: true }, e => {
if (e) {
console.error(e);
} else {
console.log('Success');
}
});
}
のように使えますcreateDirectories('/components/widget/widget.js');。
そしてもちろん、おそらく、async / awaitでpromiseを使用して、ディレクトリの作成時にファイルをより読みやすく同期的に見る方法でファイルの作成を活用することで、もっと豪華にしたいと思うでしょう。しかし、それは質問の範囲を超えています。
1行バージョンに興味がある人のために。:)
//or in typescript: import * as fs from 'fs';
const fs = require('fs');
!fs.existsSync(dir) && fs.mkdirSync(dir);
mkdirフォルダーが存在する場合は、エラーを使用してキャッチできます。
これは非同期(ベストプラクティス)で安全です。
fs.mkdir('/path', err => {
if (err && err.code != 'EEXIST') throw 'up'
.. safely do your stuff here
})
(オプションで、モードに2番目の引数を追加します。)
他の考え:
thenを使用するか、ネイティブのpromisifyを使用して待つことができます。
const util = require('util'), fs = require('fs');
const mkdir = util.promisify(fs.mkdir);
var myFunc = () => { ..do something.. }
mkdir('/path')
.then(myFunc)
.catch(err => { if (err.code != 'EEXIST') throw err; myFunc() })
(テストされていない)のような独自のpromiseメソッドを作成できます。
let mkdirAsync = (path, mode) => new Promise(
(resolve, reject) => mkdir (path, mode,
err => (err && err.code !== 'EEXIST') ? reject(err) : resolve()
)
)
同期チェックでは、以下を使用できます。
fs.existsSync(path) || fs.mkdirSync(path)または、ライブラリを使用することもできます。
mkdir('/path').catch(err => { if (err.code != 'EEXIST') throw err;}).then(myFunc);
!==代わりに使用!=
最良の解決策は、node-fs-extraと呼ばれるnpmモジュールを使用することです。それはmkdirあなたが言及したディレクトリを作成すると呼ばれるメソッドを持っています。長いディレクトリパスを指定すると、親フォルダーが自動的に作成されます。モジュールはnpmモジュールのスーパーセットであるfsためfs、このモジュールを追加すると、すべての関数を使用できます。
var dir = 'path/to/dir';
try {
fs.mkdirSync(dir);
} catch(e) {
if (e.code != 'EEXIST') throw e;
}
fs.exists()は非推奨であると記載されてfs.existsSync()いますが、非推奨ではありません。fs.existsSync()減価償却済みであることを示すリンクをリソースに追加できますか?
Apr 2018:nodejs.org/api/fs.html#fs_fs_existssync_path
ENOENT:そのようなファイルまたはディレクトリはありません
解決
const fs = require('fs') // in javascript
import * as fs from "fs" // in typescript
import fs from "fs" // in typescript
// it will create the directory if it does not exist.
!fs.existsSync(`./assets/`) && fs.mkdirSync(`./assets/`, { recursive: true })
私はjosh3736の回答のTypescript Promiseリファクタリングを追加したいと思います。
これは同じことを行い、同じエッジケースを持ちます。たまたまPromises、typescript typedefsを使用し、「use strict」で動作します。
// https://en.wikipedia.org/wiki/File_system_permissions#Numeric_notation
const allRWEPermissions = parseInt("0777", 8);
function ensureFilePathExists(path: string, mask: number = allRWEPermissions): Promise<void> {
return new Promise<void>(
function(resolve: (value?: void | PromiseLike<void>) => void,
reject: (reason?: any) => void): void{
mkdir(path, mask, function(err: NodeJS.ErrnoException): void {
if (err) {
if (err.code === "EEXIST") {
resolve(null); // ignore the error if the folder already exists
} else {
reject(err); // something else went wrong
}
} else {
resolve(null); // successfully created folder
}
});
});
}
ノード10 + ES6の場合:
import path from 'path';
import fs from 'fs';
(async () => {
const dir = path.join(__dirname, 'upload');
try {
await fs.promises.mkdir(dir);
} catch (error) {
if (error.code === 'EEXIST') {
// Something already exists, but is it a file or directory?
const lstat = await fs.promises.lstat(dir);
if (!lstat.isDirectory()) {
throw error;
}
} else {
throw error;
}
}
})();
次の例のように、ノードファイルシステムコマンドfs.statを使用してdirが存在するかどうかを確認し、fs.mkdirを使用してコールバック付きのディレクトリを作成するか、fs.mkdirSyncを使用してコールバックなしのディレクトリを作成できます。
//first require fs
const fs = require('fs');
// Create directory if not exist (function)
const createDir = (path) => {
// check if dir exist
fs.stat(path, (err, stats) => {
if (stats.isDirectory()) {
// do nothing
} else {
// if the given path is not a directory, create a directory
fs.mkdirSync(path);
}
});
};
次に、ディレクトリを再帰的に作成するための小さな関数を示します。
const createDir = (dir) => {
// This will create a dir given a path such as './folder/subfolder'
const splitPath = dir.split('/');
splitPath.reduce((path, subPath) => {
let currentPath;
if(subPath != '.'){
currentPath = path + '/' + subPath;
if (!fs.existsSync(currentPath)){
fs.mkdirSync(currentPath);
}
}
else{
currentPath = subPath;
}
return currentPath
}, '')
}