अगर यह Node.js का उपयोग करके मौजूद नहीं है, तो एक निर्देशिका कैसे बनाएं?


652

क्या यह निर्देशिका बनाने का सही तरीका है अगर यह मौजूद नहीं है। इसके पास स्क्रिप्ट के लिए पूरी अनुमति होनी चाहिए और दूसरों द्वारा पठनीय हो।

var dir = __dirname + '/upload';
if (!path.existsSync(dir)) {
    fs.mkdirSync(dir, 0744);
}

जवाबों:


1273
var fs = require('fs');
var dir = './tmp';

if (!fs.existsSync(dir)){
    fs.mkdirSync(dir);
}

28
यदि आप ऐप बूट या इनिशियलाइज़ेशन पर इस ऑपरेशन को कर रहे हैं, तो इसका निष्पादन निष्पादन को ठीक करने के लिए है जैसा कि आप इसे async करने के लिए करते हैं। यदि आप एक आवर्ती ऑपरेशन के रूप में एक निर्देशिका बना रहे हैं, तो इसका बुरा अभ्यास, लेकिन शायद कोई भी प्रदर्शन समस्या पैदा नहीं करेगा, लेकिन इसका खराब हबबिट कोई भी नहीं है। केवल अपने ऐप को बूट करने के लिए या अन्यथा एक समय के संचालन के लिए उपयोग करें।
tsturzl

20
- existsSync () पदावनत नहीं है, मौजूद है (), हालांकि है nodejs.org/api/fs.html#fs_fs_existssync_path
इयान चाडविक

* Syncविधियों का उपयोग करना आम तौर पर एक नहीं-नहीं है: इवेंट लूप को ब्लॉक नहीं करना चाहते
मैक्स हाइबर

14
स्थानीय स्क्रिप्ट के लिए सिंक विधियों का उपयोग करना ठीक है और इस तरह, स्पष्ट रूप से सर्वर के लिए अच्छा विचार नहीं है।
पियर

यदि वह ब्लॉक सेटटाइमआउट से घिरा हुआ है, तो यह async है .....................
ब्रायन ग्रेस

185

नहीं, कई कारणों से।

  1. pathमॉड्यूल एक भी नहीं है exists/ existsSyncविधि। यह fsमॉड्यूल में है। (शायद आपने अपने प्रश्न में केवल एक टाइपो बनाया है?)

  2. डॉक्स स्पष्ट रूप से आपको उपयोग करने से हतोत्साहित करता हैexists

    fs.exists()एक ऐतिहासिकता है और केवल ऐतिहासिक कारणों से मौजूद है। अपने कोड में इसका उपयोग करने का कोई कारण नहीं होना चाहिए।

    विशेष रूप से, पता चल सके कि उद्घाटन से पहले एक फ़ाइल मौजूद है यह एक विरोधी पैटर्न है कि पत्ते आप दौड़ की स्थिति के लिए असुरक्षित है: किसी अन्य प्रक्रिया के लिए कॉल के बीच फ़ाइल निकाल सकते हैं fs.exists()और fs.open()। बस फ़ाइल खोलें और जब यह नहीं है तो त्रुटि को संभालें।

    चूंकि हम एक फ़ाइल के बजाय एक निर्देशिका के बारे में बात कर रहे हैं, इस सलाह का अर्थ है कि आपको बिना शर्त कॉल करना चाहिए mkdirऔर अनदेखा करना चाहिए EEXIST

  3. सामान्य तौर पर, आपको * से बचना चाहिएSync विधियों । वे अवरुद्ध कर रहे हैं, जिसका अर्थ है कि डिस्क पर जाते समय आपके कार्यक्रम में कुछ और नहीं हो सकता है। यह एक बहुत ही महंगा ऑपरेशन है, और इसमें लगने वाला समय नोड के ईवेंट लूप की मुख्य धारणा को तोड़ता है।

    * Syncविधियाँ आमतौर पर एकल-उद्देश्य वाली त्वरित लिपियों में ठीक होती हैं (जो एक काम करती हैं और फिर बाहर निकलती हैं), लेकिन जब आप सर्वर लिख रहे हों तो इसका उपयोग कभी नहीं किया जाना चाहिए: आपका सर्वर पूरी अवधि के लिए किसी का भी जवाब देने में असमर्थ होगा। I / O अनुरोधों की। यदि कई क्लाइंट अनुरोधों के लिए I / O संचालन की आवश्यकता होती है, तो आपका सर्वर बहुत जल्दी रुक जाएगा।


    Syncएक सर्वर अनुप्रयोग में * विधियों का उपयोग करने के बारे में विचार करने का एकमात्र समय मैं स्टार्टअप में एक बार (और केवल एक बार) होता है । उदाहरण के लिए, 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
});

बेशक, यह किनारे के मामलों की तरह नहीं है

  • यदि आपका प्रोग्राम चल रहा हो तो फ़ोल्डर डिलीट हो जाता है तो क्या होता है? (यह मानते हुए कि आप स्टार्टअप के दौरान एक बार मौजूद हैं)
  • यदि फ़ोल्डर पहले से मौजूद है लेकिन गलत अनुमतियों के साथ क्या होता है?

1
वहाँ एक तरीका है SyntaxError से बचने के लिए: ऑक्टिकल शाब्दिकों को सख्त मोड में अनुमति नहीं है?
हिसर

8
इसे एक दशमलव के रूप में लिखें। 0744 == 484
josh3736

3
एक विकल्प एक मॉड्यूल का उपयोग करना है जो इस कार्यक्षमता जैसे कि github.com/jprichardson/node-fs-extra
Bret

क्या यह "मुखौटा" झंडा बात 2019 में अभी भी प्रासंगिक है? इसका उद्देश्य क्या था?
ओल्डबॉय

यह यूनिक्स फाइल मोड है - डायरेक्टरी की रीड / राइट परमिशन।
josh3736

44

मैंने पाया है और npm मॉड्यूल जो इसके लिए एक आकर्षण की तरह काम करता है। यह बस जरूरत पड़ने पर एक पुनरावर्ती mkdir करता है, जैसे "mkdir -p"।

https://www.npmjs.com/package/mkdirp


33

इस mkdirपद्धति में किसी भी निर्देशिका को पुनरावृत्ति करने की क्षमता है जो मौजूद नहीं है, और जो करते हैं उसे अनदेखा करें।

से नोड v10 / 11 डॉक्स :

// 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 / प्रतीक्षा के साथ वादों का उपयोग करके अधिक फैंसी प्राप्त करना चाहेंगे; लेकिन, यह सवाल के दायरे से परे है।


1
क्यों const __dirname = path.resolve (); और अंतर्निहित __dirname का उपयोग नहीं करते हैं?
TamusJRoyce


20

mkdirयदि फ़ोल्डर मौजूद है, तो आप बस त्रुटि का उपयोग और पकड़ सकते हैं ।
यह async (इतना अच्छा अभ्यास) और सुरक्षित है।

fs.mkdir('/path', err => { 
    if (err && err.code != 'EEXIST') throw 'up'
    .. safely do your stuff here  
    })

(वैकल्पिक रूप से मोड के साथ दूसरा तर्क जोड़ें।)


अन्य विचार:

  1. आप तब उपयोग कर सकते थे या देशी प्रॉमिस का उपयोग करके इंतजार कर सकते थे

    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() })
  2. आप अपना खुद का वादा विधि बना सकते हैं, कुछ इस तरह (अप्रकाशित):

    let mkdirAsync = (path, mode) => new Promise(
       (resolve, reject) => mkdir (path, mode, 
          err => (err && err.code !== 'EEXIST') ? reject(err) : resolve()
          )
       )
  3. तुल्यकालिक जाँच के लिए, आप उपयोग कर सकते हैं:

    fs.existsSync(path) || fs.mkdirSync(path)
  4. या आप एक पुस्तकालय का उपयोग कर सकते हैं, दो सबसे लोकप्रिय जा रहा है


1
# 1 के आशाजनक दृष्टिकोण के लिए, आप कैच को फिर से व्यवस्थित कर सकते हैं। mkdir('/path').catch(err => { if (err.code != 'EEXIST') throw err;}).then(myFunc);
क्या कूल होगा

और !==इसके बजाय का उपयोग करें!=
क्वेंटिन रॉय

18

साथ FS-अतिरिक्त पैकेज आप के साथ ऐसा कर सकते हैं एक एक लाइनर :

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

const dir = '/tmp/this/path/does/not/exist';
fs.ensureDirSync(dir);

ऐसा अंडररेटेड जवाब! fs-extra ने मेरे लिए एक नाम दिया है। मुझे लगता है कि एक फ़ोल्डर मौजूद है या नहीं, यह जांचने के लिए 10+ रेखाओं को लिखने के लिए यह एक अपमानजनक है ...
538ROMEO

10

सबसे अच्छा समाधान नोड-एफएस-एक्सट्रा नामक एनपीएम मॉड्यूल का उपयोग करना होगा । इसमें एक विधि है, mkdirजो आपके द्वारा उल्लिखित निर्देशिका बनाता है। यदि आप एक लंबी निर्देशिका पथ देते हैं, तो यह स्वचालित रूप से मूल फ़ोल्डर बना देगा। मॉड्यूल npm मॉड्यूल का एक सुपर सेट है fs, इसलिए fsयदि आप इस मॉड्यूल को जोड़ते हैं , तो आप सभी फ़ंक्शन का उपयोग कर सकते हैं ।


6
var dir = 'path/to/dir';
try {
  fs.mkdirSync(dir);
} catch(e) {
  if (e.code != 'EEXIST') throw e;
}

4
Node.js v7.4.0 के लिए, प्रलेखन बताता है कि वंचित fs.exists()है, लेकिन fs.existsSync()ऐसा नहीं है। क्या आप यह कहते हुए एक स्रोत से लिंक जोड़ सकते हैं जो fs.existsSync()मूल्यह्रास है?
फ्रांसिस

1
कोड-केवल उत्तर उन उपयोगकर्ताओं के लिए बहुत उपयोगी नहीं हैं जो भविष्य में इस प्रश्न पर आते हैं। कृपया अपने उत्तर को यह समझाने के लिए संपादित करें कि आपका कोड मूल समस्या क्यों हल करता है
yivi

3
@francis, हम्म, मैं Node.js v5, nodejs.org/docs/latest-v5.x/api/fs.html#fs_fs_existssync_path
Ping.Goblue

1
धन्यवाद! ऐसा लगता है कि समारोह संस्करण 0.12 में ही अस्तित्व में, संस्करण 4 और 5 में पदावनत हो गया और संस्करण 6 और 7 में बहाल हो गया ... एक zombi समारोह का प्रकार ...
फ्रांसिस

1
हां, जाहिरा तौर पर अब इसे अपदस्थ नहीं किया जा सकता है Apr 2018: नोडज्स.ओआरपी ./api/fs.html#fs_fs_existssync_path
LeOn - हान ली

5
    var filessystem = require('fs');
    var dir = './path/subpath/';

    if (!filessystem.existsSync(dir)){
        filessystem.mkdirSync(dir);
    }else
    {
        console.log("Directory already exist");
    }

इससे आपको मदद मिल सकती है :)


5

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

1
यह काम कर रहा है, धन्यवाद
अलजोन यामरो

3

मैं josh3736 के उत्तर का एक टाइपस्क्रिप्ट प्रॉमिस रिफैक्टर जोड़ना चाहूंगा ।

यह एक ही काम करता है और एक ही किनारे के मामले हैं, यह सिर्फ वादों, टाइपस्क्रिप्ट टाइप का उपयोग करने के लिए होता है और "सख्त से सख्त" काम करता है।

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

3

नोड 10 + ईएस 6 के साथ:

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

2

आप कॉल फ़ाइल सिस्टम कमांड 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);
        }
    });
};

1

यहाँ पुनरावर्ती निर्देशिका बनाने का एक छोटा सा कार्य है:

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
  }, '')
}

0

Async / प्रतीक्षा का उपयोग करना:

const mkdirP = async (directory) => {
  try {
    return await fs.mkdirAsync(directory);
  } catch (error) {
    if (error.code != 'EEXIST') {
      throw e;
    }
  }
};

आपको प्रॉमिस करना होगा fs:

import nodeFs from 'fs';
import bluebird from 'bluebird';

const fs = bluebird.promisifyAll(nodeFs);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.