Node.js Ordner erstellen oder vorhandene verwenden

186

Ich habe bereits die Dokumentation von Node.js gelesen und es sei denn, ich habe etwas verpasst, es sagt nicht aus, was die Parameter insbesondere in bestimmten Operationen enthalten fs.mkdir(). Wie Sie in der Dokumentation sehen können, ist es nicht sehr viel.

Derzeit habe ich diesen Code, der versucht, einen Ordner zu erstellen oder stattdessen einen vorhandenen zu verwenden:

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

Aber ich frage mich, ob dies der richtige Weg ist? Ist das Überprüfen des Codes EEXISTder richtige Weg, um festzustellen, dass der Ordner bereits vorhanden ist? Ich weiß, dass ich das tun kann, fs.stat()bevor ich das Verzeichnis erstelle, aber das wären bereits zwei Treffer für das Dateisystem.

Zweitens gibt es eine vollständige oder zumindest detailliertere Dokumentation von Node.js, die Details darüber enthält, welche Fehlerobjekte enthalten, welche Parameter bedeuten usw.

Joseph
quelle
31
Kleiner Trottel, aber loswerden e &&. Wenn dies !efehlschlägt, wissen Sie, dass ees wahr ist.
Ich hasse Lazy

Antworten:

236

Ein guter Weg, dies zu tun, ist die Verwendung des Moduls mkdirp .

$ npm install mkdirp

Verwenden Sie diese Option, um eine Funktion auszuführen, für die das Verzeichnis erforderlich ist. Der Rückruf wird aufgerufen, nachdem der Pfad erstellt wurde oder wenn der Pfad bereits vorhanden war. Der Fehler errwird gesetzt, wenn mkdirp den Verzeichnispfad nicht erstellen konnte.

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

    // path exists unless there was an error

});
Teemu Ikonen
quelle
3
Es scheint mir, dass die richtige Antwort (lesen Sie 'keine Abhängigkeit hinzugefügt') die Antwort von @Raugaral ist fs.exists(Sync).
Ricardo Pedroni
@meawoppl, es ist 'makedirectory'p. Das 'p' ist unbekannt.
Andrew
4
@ RicardoPedroni Der richtige Weg ist die Verwendung eines Moduls. Module versuchen normalerweise von ganzem Herzen, ein Problem zu lösen, und werden oft gewartet. Sie können sie einfach mit npm aktualisieren. Außerdem sollten Sie die Verwendung von fs.exists [Sync] ausdrücklich vermeiden, da die Verwendung Rennbedingungen impliziert.
1j01
16
@ 1j01 Ich glaube nicht, dass der richtige Weg darin besteht, ein Modul zu verwenden, wenn die Plattform den Vorgang nativ unterstützt. Das ist ein Weg zum Chaos. Ich muss zustimmen, dass es aus technischer Sicht bessere Antworten gibt.
c ..
2
@ 1j01 Die Verwendung von Synchronisierungsvorgängen impliziert auch Rennbedingungen, da ihre Verwendung für sie eine Lösung darstellt.
c ..
192

Bearbeiten: Da diese Antwort sehr beliebt ist, habe ich sie aktualisiert, um aktuelle Praktiken widerzuspiegeln.

Knoten> = 10

Die neue { recursive: true }Option von Node's fsermöglicht dies jetzt nativ. Diese Option ahmt das Verhalten von UNIX nach mkdir -p. Es stellt rekursiv sicher, dass jeder Teil des Pfads vorhanden ist, und gibt keinen Fehler aus, wenn einer von ihnen dies tut.

(Hinweis: Es kann immer noch Fehler wie EPERModer EACCESSauslösen, also wickeln Sie es besser in ein, try {} catch (e) {}wenn Ihre Implementierung dafür anfällig ist.)

Synchrone Version.

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

Asynchrone Version

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

Ältere Knotenversionen

Mit a try {} catch (err) {}können Sie dies sehr elegant erreichen, ohne auf eine Rennbedingung zu stoßen.

Um eine Totzeit zwischen der Überprüfung der Existenz und der Erstellung des Verzeichnisses zu vermeiden, versuchen wir einfach, es direkt zu erstellen, und ignorieren den Fehler, falls dies der Fall ist EEXIST (Verzeichnis existiert bereits).

Wenn der Fehler jedoch nicht EEXISTvorliegt, sollten wir einen Fehler auslösen, da es sich möglicherweise um ein EPERModer handeltEACCES

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

Für mkdir -p-ähnlichen rekursive Verhalten, zum Beispiel ./a/b/c, würden Sie sie auf jedem Teil der dirpath nennen müssen, zum Beispiel ./a, ./a/b,.a/b/c

Christophe Marois
quelle
var fs = Npm.require ('fs'); var dir = process.env.PWD + '/ files / users /' + this.userId + '/'; try {fs.mkdirSync (dir); } catch (e) {if (e.code! = 'EEXIST') throw e; }
Aaron
Ich habe Ihren Code ausprobiert und ein js-Skript erstellt, das die Katalogerstellung wie folgt verwendet: mkdirpSync (path.join (__ dirname, 'first', 'second', 'Third', 'ololol', 'works')); Aber habe diesen Fehler bekommen: $ node 1.js fs.js: 747 return binding.mkdir (pathModule._makeLong (path), ^ Fehler: EPERM, Operation nicht erlaubt 'C: \' bei Fehler (native) bei Object.fs. mkdirSync (fs.js: 747: 18) unter mkdirpSync (C: \ Benutzer \ MAXIM \ Desktop \ test \ 1.js: 15: 8) unter Objekt. <anonym> (C: \ Benutzer \ MAXIM \ Desktop \ test \ 1.js: 19: 1) ... Könnten Sie vorschlagen, was falsch sein könnte? Wird offensichtlich unter Windows verwendet :)
Alendorff
EPERM scheint ein Erlaubnisproblem zu sein, daher würde das Skript ohnehin eine fehlerhafte Ausführung enthalten
Christophe Marois,
Ich denke, das wäre besser: var mkdirpSync = function (dirpath) {var parts = dirpath.split (path.sep); für (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; }}}}
manish
1
Warnung: Es funktioniert nicht, wenn Ihr Pfad mit einem /
acemtp
62

Wenn Sie einen schnell und schmutzigen Einzeiler wünschen, verwenden Sie diesen:

fs.existsSync("directory") || fs.mkdirSync("directory");
marekventur
quelle
1
fs.existsist veraltet: nodejs.org/api/fs.html#fs_fs_exists_path_callback
adius
7
fs.existsSync (...) ist jedoch nicht veraltet, daher scheint diese Antwort in Ordnung zu sein.
Dan Haywood
Kopf hoch! Funktioniert nicht für "dir / foo / bar", dh es fehlt die Funktion mkdir -p flag
Karl Pokus
Dies hat auch eine Rennbedingung
Evert
26

Die docs von node.js für werden fs.mkdirgrundsätzlich auf die Linux-Manpage für verschobenmkdir(2) . Dies zeigt an, dass dies EEXISTauch angezeigt wird, wenn der Pfad vorhanden ist, es sich jedoch nicht um ein Verzeichnis handelt, das bei dieser Route einen unangenehmen Eckfall erzeugt.

Sie können besser anrufen fs.stat , um festzustellen, ob der Pfad vorhanden ist und ob es sich um ein Verzeichnis in einem einzelnen Aufruf handelt. Für den Normalfall, in dem das Verzeichnis bereits vorhanden ist, handelt es sich nur um einen einzigen Dateisystem-Treffer.

Bei diesen fsModulmethoden handelt es sich um Thin Wrapper um die nativen C-APIs. Sie müssen daher die Manpages überprüfen, auf die in den Dokumenten von node.js verwiesen wird, um Einzelheiten zu erfahren.

JohnnyHK
quelle
19
Der Aufruf , statbevor mkdirdas Potenzial für eine Race - Bedingung hat - dies im Auge behalten.
Roger Lipscombe
24

Sie können dies verwenden:

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");
        }
    });
}
Raugaral
quelle
1
-1. Ich glaube nicht, dass dies funktioniert, statSyncwird einen Fehler auslösen, wenn die Entität überhaupt nicht existiert und den Code zum Absturz bringt. Sie müssen dies in einen try/catchBlock einschließen.
Chris Foster
2
Entschuldigung, ich habe Unrecht. Ändern Sie "statSync" für "existesSync"
Raugaral
5
Laut nodejs.org/api/fs.html#fs_fs_mkdirsync_path_mode akzeptiert die Sync-Variante von mkdir keinen Rückruf
danwellman
1
Nach nodejs.org/api/fs.html#fs_fs_existssync_path , fs.existsSync()und fs.exists()wird als veraltet.
pau.moreno
7

Ich schlage eine Lösung ohne Module vor (das Sammeln von Modulen wird aus Gründen der Wartbarkeit niemals empfohlen, insbesondere für kleine Funktionen, die in wenigen Zeilen geschrieben werden können ...):

LETZTES UPDATE :

In Version 10.12.0 implementieren NodeJS rekursive Optionen:

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

UPDATE:

// 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');
Liberateur
quelle
fs.exists()ist in Knoten v9 veraltet. Verwenden Sie fs.access()stattdessen. ( undefinedENOENT
Gibt
Ohne npm-Paket funktioniert es. Es ist ein wertvoller Code. Vielen Dank
Karthik Sridharan
Dieser ist viel besser, um einen Ordner unter einem vorhandenen langen Pfad zu erstellen;) Danke, Mann.
Tsung Goh
1
Was ist mit fs.mkdirSync('my/new/folder/create', {recursive: true})?
Saitho
Vielen Dank ! Ich aktualisiere meinen Beitrag, um anderen zu helfen. Knoten 10.12.0 war zu neu.
Liberateur
4

Hier ist der ES6-Code, mit dem ich ein Verzeichnis erstelle (wenn es nicht existiert):

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

Hinweis:

  • Am Anfang der createDirectoryFunktion, ich den Weg zu garantieren normalisieren , dass der Pfad seperator Typ des Betriebssystems konsequent genutzt werden (zB dies wird sich C:\directory/testin C:\directory\test(unter Windows ist)
  • fs.existsist veraltet , deshalb fs.statüberprüfe ich , ob das Verzeichnis bereits existiert
  • Wenn ein Verzeichnis nicht vorhanden ist , wird der Fehlercode sein ENOENT( E rror NO ENT ry)
  • Das Verzeichnis selbst wird mit erstellt fs.mkdir
  • Ich bevorzuge die asynchrone Funktion fs.mkdirgegenüber dem blockierenden Gegenstück fs.mkdirSyncund aufgrund des Umbruchs Promisewird garantiert, dass der Pfad des Verzeichnisses erst zurückgegeben wird, nachdem das Verzeichnis erfolgreich erstellt wurde
Benny Neugebauer
quelle
Vielen Dank für eine saubere Lösung, die keine unnötigen Module beinhaltet. Es hat perfekt für mich funktioniert. Ich wünschte, es gäbe mehr Antworten wie diese!
Ken Lyon
3

Meiner Meinung nach sollten Sie die Dateisystem-Treffer beim Codieren in Javascript besser nicht zählen. Wenn Sie jedoch (1) stat& mkdirund (2) mkdirden Fehlercode überprüfen (oder verwerfen), sind beide Möglichkeiten die richtigen, um das zu tun, was Sie wollen.

Chul-Woong Yang
quelle
-1, ich sehe nicht ein, wie das Überprüfen oder Verwerfen beide richtige Wege sein könnten, dies zu tun. Dies ist so ziemlich eine Nichtantwort.
Matt Ball
Es ist eine gute Möglichkeit, ein Verzeichnis zu erstellen oder ein vorhandenes zu verwenden. Ich verstehe nicht, warum du nicht siehst. Das Überprüfen des Fehlercodes ist höflich gut, während das Verwerfen des Fehlercodes nur gut ist. stimmst du nicht zu
Chul-Woong Yang
1
Vielleicht ist dies ein Problem mit Sprachbarrieren, aber ich habe dies so gelesen, dass ich die Frage, die das OP stellt, einfach nicht beantworte.
Matt Ball
Ich verstehe, worum es dir geht. Ich glaube jedoch, dass es viele Möglichkeiten gibt, die Dinge richtig zu machen. Vielen Dank.
Chul-Woong Yang
2

Erstellen Sie ein dynamisches Namensverzeichnis für jeden Benutzer. Verwenden Sie diesen Code

***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");
}
Adiii
quelle
1

All dies können Sie mit dem Dateisystemmodul tun.

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

Sie müssen wirklich nicht einmal überprüfen, ob das Verzeichnis vorhanden ist. Der folgende Code garantiert auch, dass das Verzeichnis entweder bereits vorhanden ist oder erstellt wurde.

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.
})
alter Junge
quelle
0

Raugarals Antwort, aber mit -p-Funktionalität. Hässlich, aber es funktioniert:

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
user8675309
quelle
0

Eine neuere Alternative zu Teemu Ikonens Antwort , die sehr einfach und leicht lesbar ist, ist die Verwendung der ensureDirMethode desfs-extra Paketmethode.

Es kann nicht nur als offensichtlicher Ersatz für das eingebaute fsModul verwendet werden, sondern verfügt neben den Funktionen des Moduls auch über viele andere Funktionenfs Pakets .

Die ensureDirMethode stellt, wie der Name schon sagt, sicher, dass das Verzeichnis vorhanden ist. Wenn die Verzeichnisstruktur nicht vorhanden ist, wird sie erstellt. Mögenmkdir -p . Nicht nur der Endordner, sondern der gesamte Pfad wird erstellt, falls noch nicht vorhanden.

Die oben angegebene ist die asyncVersion davon. Es gibt auch eine synchrone Methode, um dies in Form der ensureDirSyncMethode durchzuführen .

Rai
quelle
0

Die Antwort von @ Liberateur oben hat bei mir nicht funktioniert (Node v8.10.0). Kleine Modifikationen haben den Trick gemacht, aber ich bin mir nicht sicher, ob dies der richtige Weg ist. Bitte vorschlagen.

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