Node.js klasör oluştur veya mevcut olanı kullan


186

Zaten Node.js belgelerini okudum ve bir şey kaçırmazsam, özellikle belirli işlemlerde parametrelerin ne içerdiğini söylemez fs.mkdir(). Belgelerde gördüğünüz gibi, çok fazla değil.

Şu anda, bir klasör oluşturmaya veya bunun yerine varolan bir klasörü kullanmaya çalışan bu kodu var:

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

Ama merak ediyorum bunu yapmanın doğru yolu bu mu? Kodun kontrol EEXISTedilmesi, klasörün zaten var olduğunu bilmenin doğru yolu mu? Ben fs.stat()dizin yapmadan önce yapabileceğimi biliyorum , ama bu zaten dosya sistemine iki hit olurdu.

İkinci olarak, Node.js'nin hangi hata nesnelerinin içerdiği, hangi parametrelerin ne anlama geldiği vb.


31
Küçük nitpick, ama kurtulmak e &&. Eğer !ebaşarısız olursa, o zaman doğru olduğunu bilirsiniz e.
Tembel Nefret Ediyorum

Yanıtlar:


236

Bunu yapmanın iyi bir yolu mkdirp modülünü kullanmaktır .

$ npm install mkdirp

Dizini gerektiren işlevi çalıştırmak için kullanın. Yol oluşturulduktan sonra veya yol zaten mevcutsa geri arama çağrılır. errMkdirp dizin yolu oluşturamazsa hata ayarlanır.

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

    // path exists unless there was an error

});

3
Bana öyle geliyor (okuma 'bağımlılık eklenmedi') cevabı, düşük tarafından @Raugaral, kullanarak olurdu fs.exists(Sync).
Ricardo Pedroni

@meawoppl, 'makedirectory'p. 'P' bilinmiyor.
Andrew

4
@RicardoPedroni Doğru yol bir modül kullanmaktır. Modüller genellikle yürekten bir sorunu çözmeye çalışır ve genellikle korunur. Bunları npm ile kolayca güncelleyebilirsiniz. Ayrıca, kullanımı yarış koşullarını ifade ettiği için fs.exists [Sync] kullanmaktan özellikle kaçınmalısınız.
1j01

16
@ 1j01 Platform, işlemi yerel olarak destekliyorsa, doğru yolun bir modül kullanmak olduğuna inanmıyorum. Bu kaosa giden bir yol. Teknik açıdan daha iyi cevaplar olduğu konusunda hemfikirim.
c ..

2
@ 1j01 Ayrıca, Sync işlemlerini kullanmak, yarış koşullarını ima eder, çünkü kullanımları onlar için bir çözümdür.
c ..

193

Edit: Bu cevap çok popüler olduğu için, güncel uygulamaları yansıtacak şekilde güncelledim.

Düğüm> = 10

{ recursive: true }Düğümlerin yeni seçeneği fsartık buna doğal olarak izin veriyor. Bu seçenek UNIX'lerin davranışlarını taklit eder mkdir -p. Yolun her bölümünün yinelemeli olarak olmasını sağlar ve bunlardan herhangi biri varsa hata atmaz.

(Not: yine de EPERMveya gibi hatalar atabilir EACCESS, bu yüzden try {} catch (e) {}uygulamanız buna duyarlıysa daha iyi sarın .)

Senkron versiyon.

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

Zaman uyumsuz sürüm

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

Eski Düğüm sürümleri

A kullanarak try {} catch (err) {}, bunu bir yarış durumu ile karşılaşmadan çok zarif bir şekilde başarabilirsiniz.

Varlığı denetleme ve dizini oluşturma arasındaki ölü zamanı önlemek için, dizini doğrudan oluşturmaya çalışırız ve varsa hatayı göz ardı ederiz EEXIST(dizin zaten var).

EEXISTAncak hata değilse , bir hata atmalıyız, çünkü bir EPERMveyaEACCES

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

İçin mkdir -p-like özyinelemeli davranış, örneğin ./a/b/c, sen dirpath her bölümünde üzerinde demelisiniz, örneğin ./a, ./a/b,.a/b/c


var fs = Npm.require ('fs'); var dir = process.env.PWD + '/ dosya / kullanıcı /' + this.userId + '/'; {fs.mkdirSync (dir) komutunu deneyin; } catch (e) {if (e.code! = 'EEXIST') e atın; }
Aaron

Kodunuzu denedim, böyle katalog oluşturma kullanan bir js-script oluşturmak: mkdirpSync (path.join (__ dirname, 'ilk', 'ikinci', 'üçüncü', 'ololol', 'çalışır')); Ancak şu hatayı aldım: $ node 1.js fs.js: 747 return bağlama.mkdir (pathModule._makeLong (yol), ^ Hata: EPERM, Object.fs dosyasında Error (yerel) 'C: \' işlemine izin verilmiyor. mkdirpSync şirketinde mkdirSync (fs.js: 747: 18) Object'de (C: \ Users \ MAXIM \ Desktop \ test \ 1.js: 15: 8). <anonymous> (C: \ Users \ MAXIM \ Desktop \ test \ 1.js: 19: 1) ... Neyin yanlış olabileceğini önerebilir misiniz? Açıkça pencerelerde kullanılır :)
Alendorff

EPERM bir izin sorunu gibi görünüyor, bu yüzden senaryo yine de yürütmeyi
bozmuş olacak

Bence daha iyi olurdu: var mkdirpSync = function (dirpath) {var parts = dirpath.split (path.sep); for (var i = 1; i <= parts.length; i ++) {deneyin {fs.mkdirSync (path.join.apply (null, parts.slice (0, i))); } catch (hata) {if (error.code! = 'EEXIST') {atış hatası; }}}}
manish

1
uyarı: yolunuz bir /
acemtp

62

Hızlı ve kirli bir astar istiyorsanız, bunu kullanın:

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

1
fs.existskullanımdan kaldırıldı: nodejs.org/api/fs.html#fs_fs_exists_path_callback
adius

7
Bununla birlikte, fs.existsSync (...) kullanımdan kaldırılmamıştır, bu nedenle bu cevap iyi görünüyor.
Dan Haywood

Dikkat et! "Dir / foo / bar" için çalışmayacak yani mkdir -p bayrak özelliği yok
Karl Pokus

Bu aynı zamanda bir yarış durumu var
Evert

26

Node.js, fs.mkdirtemelde Linux kılavuz sayfasına ertelendi mkdir(2). Bu EEXIST, yolun mevcut olması durumunda da belirtileceğini, ancak bu rotaya giderseniz garip bir köşe durumu oluşturan bir dizin olmadığını gösterir.

fs.statAramanın daha iyi bir yolu olabilir, bu da yolun mevcut olup olmadığını ve tek bir çağrıda bir dizin olup olmadığını söyler. Dizin zaten var olduğu normal durumda (varsayalım), sadece tek bir dosya sistemi isabet.

Bu fsmodül yöntemleri, yerel C API'lerinin etrafındaki ince sarmalayıcılardır, bu nedenle ayrıntılar için node.js belgelerinde başvurulan man sayfalarını kontrol etmeniz gerekir.


19
Daha statönce çağırmanın mkdirbir yarış durumu potansiyeli vardır - bunu aklınızda bulundurun.
Roger Lipscombe

24

Bunu kullanabilirsiniz:

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. Bu işe statSyncyaramıyor, varlık hiç yoksa, kodu çökmesini bir hata atar inanmıyorum . Bunu bir try/catchbloğa sarmanız gerekiyor .
Chris Foster

2
Üzgünüm hatalıyım. "existSync" için "statSync" değiştir
Raugaral

5
Nodejs.org/api/fs.html#fs_fs_mkdirsync_path_mode'e göre mkdir eşitleme varyantı geri
aramayı

1
Göre nodejs.org/api/fs.html#fs_fs_existssync_path , fs.existsSync()ve fs.exists()kaldırılacaktır.
pau.moreno

7

Modülsüz bir çözüm öneriyorum (modülleri biriktirmek, özellikle birkaç satırda yazılabilen küçük işlevler için sürdürülebilirlik için asla tavsiye edilmez ...):

SON GÜNCELLEME :

V10.12.0'da, NodeJS uygulaması özyinelemeli seçenekler:

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

GÜNCELLEME :

// 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 düğümünde kullanımdan kaldırıldı. kullanın fs.access(). ( undefineddosya varsa geri döner ; aksi takdirde bir hata atar ENOENT)
chharvey 28:18

Herhangi bir npm paketi olmadan çalışıyor. Bu değerli bir kod. Teşekkürler
Karthik Sridharan

Bu, mevcut uzun yolun altında bir klasör oluşturmak için oldukça iyidir;) Teşekkürler, adamım.
Tsung Goh

1
Ne olmuş fs.mkdirSync('my/new/folder/create', {recursive: true})?
saitho

Teşekkürler ! Yayınımı başkalarına yardım etmek için güncelliyorum. 10.12.0 düğümü çok yeni.
Liberateur


4

İşte bir dizin oluşturmak için kullandığım ES6 kodu (yok olduğunda):

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

Not:

  • Başında createDirectoryfonksiyonu, ben (örneğin, bu dönecek işletim sisteminin yol ayırıcı tipi sürekli kullanılacağını garanti yolunu normalleştirmek C:\directory/testiçine C:\directory\test(Windows üzerinde olmaları durumunda)
  • fs.existskullanımdan kaldırıldı , bu yüzden kullanıyorumfs.stat dizinin zaten var olup olmadığını kontrol etmek için
  • Bir dizin yoksa, hata kodu ENOENT( E rror NO ENT) ry) olacaktır.
  • Dizinin kendisi kullanılarak oluşturulacaktır fs.mkdir
  • Eşzamanlı fs.mkdirengelleme karşı zaman uyumsuz işlevi tercih ve fs.mkdirSyncsarma nedeniyle Promisedizinin yolunun yalnızca dizin başarıyla oluşturulduktan sonra döndürüleceği garanti edilecektir

Gereksiz modülleri içermeyen temiz bir çözüm için teşekkür ederiz. Benim için mükemmel çalıştı. Bunun gibi daha fazla cevap olsaydı!
Ken Lyon

3

Bence Javascript'te kod yazarken dosya sistemi isabetlerini saymamak daha iyi olur. Ancak, (1) stat& mkdirve (2) mkdirve hata kodunu kontrol edin (veya atın), her iki yol da istediğinizi yapmak için doğru yoldur.


-1, kontrol etmenin veya atmanın her ikisinin de bunu yapmanın nasıl doğru yolu olabileceğini görmüyorum. Bu hemen hemen bir cevap değil.
Matt Ball

Bir dizini mkdir veya mevcut dizini kullanmak için iyi bir yoldur. Neden görmediğini anlamıyorum. Hata kodunu kontrol etmek kibarca iyi, hata kodunu atmak ise sadece iyi bir koddur. kabul etmiyor musun
Chul-Woong Yang

1
Belki bu bir dil engeli problemidir, ama bunu sadece OP'nin sorduğu soruyu cevaplamamak olarak okuyorum.
Matt Ball

Ne demek istediğini anlıyorum. Ancak, işleri doğru yapmanın birçok yolu olduğuna inanıyorum. Teşekkürler.
Chul-Woong Yang

2

her kullanıcı için dinamik ad dizini oluştur ... bu kodu kullan

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

Tüm bunları Dosya Sistemi modülüyle yapabilirsiniz.

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

Dizinin var olup olmadığını gerçekten kontrol etmeniz bile gerekmez. Aşağıdaki kod, dizinin zaten var olduğunu veya oluşturulduğunu da garanti eder.

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

Raugaral'ın yanıtı -p işlevselliği ile. Çirkin, ama işe yarıyor:

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

Tıpkı Teemu Ikonen'in cevabına çok basit ve kolayca okunabilen daha yeni bir alternatif olarak paketin ensureDiryöntemini kullanmaktır fs-extra.

Sadece dahili fsmodül için açık bir yedek olarak değil , aynı zamanda fspaketin işlevlerine ek olarak birçok başka işleve de sahiptir .

ensureDirAdından da anlaşılacağı gibi yöntem, dizinin mevcut olmasını sağlar. Dizin yapısı yoksa oluşturulur. Sevmekmkdir -p . Yalnızca bitiş klasörü değil, zaten yoksa tüm yol oluşturulur.

yukarıda verilen asyncsürümdür. Ayrıca bunu yöntem şeklinde gerçekleştirmek için eşzamanlı bir yöntemi vardır ensureDirSync.


0

@ Liberateur'un yukarıdaki cevabı benim için işe yaramadı (Düğüm v8.10.0). Küçük bir değişiklik hile yaptı ama bunun doğru bir yol olup olmadığından emin değilim. Lütfen önerin.

// 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');
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.