Node.js kullanarak yoksa bir dizin nasıl oluşturulur?


656

Varsa, bir dizin oluşturmanın doğru yolu budur. Komut dosyası için tam izne sahip olmalı ve diğerleri tarafından okunabilir olmalıdır.

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

Yanıtlar:


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

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

28
Bu işlemi uygulama önyüklemesi veya başlatma işleminde gerçekleştiriyorsanız, zaman uyumsuz olarak yapsaydınız aynı işlemi yapacağınız için yürütmeyi engelleme para cezası. Bir dizini yinelenen bir işlem olarak yapıyorsanız, bunun kötü uygulamasıdır, ancak muhtemelen herhangi bir performans sorununa neden olmaz, ancak kötü bir alışkanlık. Yalnızca uygulamanızı önyüklemek veya bir kerelik işlemler için kullanın.
tsturzl

20
existSync () kullanımdan kaldırıldı, exist () olsa da - nodejs.org/api/fs.html#fs_fs_existssync_path
Ian Chadwick

* Syncyöntemleri kullanmak genellikle
hayırdır:

14
Senkronizasyon yöntemlerini kullanmak, yerel komut dosyaları için iyidir ve böyle bir sunucu için iyi bir fikir değildir.
Pier

Bu blok setTimeout ile çevriliyse, eşzamansız .....................
Bryan Grace

185

Hayır, birçok nedenden dolayı.

  1. pathModül, bulunmamaktadır exists/ existsSyncyöntem. Bu ise fsmodül. (Belki de sorunuzda bir yazım hatası yaptınız mı?)

  2. Dokümanlar sizi kullanmanızı kesinlikle engelliyorexists .

    fs.exists()bir anakronizmdir ve sadece tarihsel nedenlerle var olur. Kendi kodunuzda kullanmak için neredeyse hiçbir zaman bir sebep olmamalıdır.

    Başka bir işlem için çağrılar arasında dosya kaldırabilir: Özellikle, bir dosya açmadan önce varsa o yapraklar o savunmasız yarış koşullarına bir anti-kalıptır kontrol fs.exists()ve fs.open(). Sadece dosyayı açın ve orada olmadığında hatayı halledin.

    Bir dosya yerine bir dizin hakkında konuştuğumuz için, bu öneri sadece koşulsuz olarak çağırmanız mkdirve görmezden gelmeniz gerektiği anlamına gelir EEXIST.

  3. Genel olarak * Syncyöntemlerinden kaçınmalısınız . Engelliyorlar, yani diske giderken programınızda kesinlikle başka hiçbir şey olamaz. Bu çok pahalı bir işlemdir ve geçen süre, düğümün olay döngüsünün temel varsayımını kırar.

    * SyncYöntemleri genellikle tek amaçlı hızlı komut dosyalarında (bir şey yapan ve sonra çıkanlar) iyidir, ancak bir sunucu yazarken neredeyse hiç kullanılmamalıdır: sunucunuz tüm süre boyunca kimseye yanıt veremez G / Ç istekleri. Birden fazla istemci isteği G / Ç işlemleri gerektiriyorsa, sunucunuz çok hızlı bir şekilde durma noktasına gelecektir.


    SyncBir sunucu uygulamasında * yöntemlerini kullanmayı düşünebileceğim tek zaman başlangıçta bir kez (ve sadece bir kez) gerçekleşen bir işlemdir . Örneğin, require aslındareadFileSync modülleri yüklemek için kullanılır.

    O zaman bile, dikkatli olmalısınız çünkü birçok senkronize G / Ç sunucunuzun başlatma süresini gereksiz yere yavaşlatabilir.


    Bunun yerine, zaman uyumsuz G / Ç yöntemlerini kullanmalısınız.

Bu tavsiyeleri bir araya getirirsek, şöyle bir şey elde ederiz:

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

Ve bunu şu şekilde kullanabiliriz:

ensureExists(__dirname + '/upload', 0744, function(err) {
    if (err) // handle folder creation error
    else // we're all good
});

Tabii ki, bu gibi son durumları açıklamaz

  • Programınız çalışırken klasör silinirse ne olur? (başlangıçta yalnızca bir kez bulunduğunu kontrol ettiğiniz varsayılarak)
  • Klasör zaten mevcut ancak yanlış izinlere sahipse ne olur?

1
kaçınmanın bir yolu var mı?
Whisher

8
Ondalık olarak yazın. 0744 == 484.
193714

3
Alternatif olarak, fs'yi
Bret

Bu "maske" bayrağı şey 2019'da hala geçerli mi? amacı neydi?
oldboy

Bu unix dosya modu - dizinin okuma / yazma izinleri.
josh3736


33

mkdirYöntem yeteneğine sahiptir yinelemeli oluşturmak bulunmayıp bir yolda bir dizin ve yapacak olanları görmezden.

Gönderen Düğüm v10 / 11 docs :

// Creates /tmp/a/apple, regardless of whether `/tmp` and /tmp/a exist.
fs.mkdir('/tmp/a/apple', { recursive: true }, (err) => {
    if (err) throw err;
});

NOT: Önce yerleşik fsmodülü içe aktarmanız gerekir .

Şimdi, yerel ES Modüllerinden (işaret etkin ve .mjs uzantısıyla) yararlanan, kök olmayan yolları işleyen ve tam yol adlarını açıklayan biraz daha sağlam bir örnek:

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

Gibi kullanabilirsiniz createDirectories('/components/widget/widget.js');.

Ve elbette, dizinler oluşturulduğunda dosya oluşturmayı daha okunabilir senkron görünümlü bir şekilde kullanmak için zaman uyumsuz / beklemede olan vaatleri kullanarak muhtemelen daha süslü olmak istersiniz; ancak bu, sorunun kapsamının dışındadır.


1
Neden const __dirname = path.resolve (); ve yerleşik __dirname kullanmıyor musunuz?
TamusJRoyce

29

Bir satır sürümü ile ilgilenen herhangi bir durumda. :)

//or in typescript: import * as fs from 'fs';
const fs = require('fs');
!fs.existsSync(dir) && fs.mkdirSync(dir);

İddia 1-astar aslında 1 satır değil.
Hibrit web dev

20

mkdirKlasör varsa hatayı kullanabilir ve yakalayabilirsiniz.
Bu zaman uyumsuz (en iyi uygulama) ve güvenlidir.

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

(İsteğe bağlı olarak modla ikinci bir bağımsız değişken ekleyin.)


Diğer düşünceler:

  1. O zaman kullanabilirsiniz veya yerel promisify kullanarak bekleyebilirsiniz .

    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. Kendi vaat yönteminizi yapabilirsiniz (denenmemiş):

    let mkdirAsync = (path, mode) => new Promise(
       (resolve, reject) => mkdir (path, mode, 
          err => (err && err.code !== 'EEXIST') ? reject(err) : resolve()
          )
       )
  3. Senkronize kontrol için şunları kullanabilirsiniz:

    fs.existsSync(path) || fs.mkdirSync(path)
  4. Veya en popüler ikisi olan bir kütüphaneyi kullanabilirsiniz


1
gelecek vaat eden yaklaşım # 1 için, yakalamayı yeniden düzenleyebilirsiniz. mkdir('/path').catch(err => { if (err.code != 'EEXIST') throw err;}).then(myFunc);
Soğuk Olacak Ne

Ve !==yerine kullanın!=
Quentin Roy

18

İle fs-ekstra paketin size ile yapabilirsiniz tek astar :

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

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

Bu kadar önemsiz bir cevap! fs-extra benim için bir zorunluluktur. Bence bir klasör olup olmadığını kontrol etmek için 10 + satır juste yazmak için bir sapma ...
538ROMEO

10

En iyi çözüm node-fs-extra adlı npm modülünü kullanmak olacaktır . mkdirBahsettiğiniz dizini oluşturan denilen bir yöntemi vardır . Uzun bir dizin yolu verirseniz, üst klasörler otomatik olarak oluşturulur. Modül süper bir npm modülü kümesidir fs, bu nedenle fsbu modülü eklerseniz tüm işlevleri de kullanabilirsiniz .


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

4
Node.js v7.4.0 için belgelerfs.exists() , kullanımdan kaldırılmış olduğunu ancak belirtilmediğini belirtir fs.existsSync(). Bir fs.existsSync()amortismana amortismana tabi olduğunu söyleyen bir bağlantı ekleyebilir misiniz ?
francis

1
Sadece kod yanıtları, gelecekte bu soruya gelen kullanıcılar için çok yararlı değildir. Lütfen kodunuzun neden orijinal sorunu çözdüğünü açıklamak için cevabınızı düzenleyin
Yivi

3
@francis, hmm, Node.js v5'e
Ping.Goblue

1
Teşekkürler! Görünüşe göre işlev 0.12 sürümünde mevcuttu, sürüm 4 ve 5'te kullanımdan kaldırıldı ve sürüm 6 ve 7'de geri yüklendi ... Bir çeşit zombi işlevi ...
francis

1
Evet, görünen o olduğu DEĞİL itibariyle artık kullanım dışı Apr 2018: nodejs.org/api/fs.html#fs_fs_existssync_path
LeOn - Han Li

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

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

Bu size yardımcı olabilir :)


5

ENOENT: böyle bir dosya veya dizin yok

Çözüm

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
bu çalışıyor, teşekkür ederim
Aljohn Yamaro

3

Josh3736'nın cevabına bir Typcript Promise refactoru eklemek istiyorum .

Aynı şeyi yapar ve aynı kenar durumlarda vardır, sadece Promises, daktilo tip tanımları kullanmak ve "katı kullanın" ile çalışır.

// 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

Düğüm 10 + ES6 ile:

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

Sen düğüm kullanabilirsiniz Dosya Sistemi komut fs.stat dir varsa ve kontrol etmek fs.mkdir geri arama ile bir dizin oluşturmak için, ya fs.mkdirSync bu örnekte olduğu gibi, geri arama olmadan bir dizin oluşturmak için:

//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

İşte dizinleri özyinelemeli olarak oluşturmak için küçük bir işlev:

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 / await kullanma:

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

Söz vermeniz gerekecek fs:

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

const fs = bluebird.promisifyAll(nodeFs);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.