Node.js crée un dossier ou utilise des


186

J'ai déjà lu la documentation de Node.js et, sauf si j'ai manqué quelque chose, elle ne dit pas ce que les paramètres contiennent dans certaines opérations, notamment fs.mkdir(). Comme vous pouvez le voir dans la documentation, ce n'est pas beaucoup.

Actuellement, j'ai ce code, qui essaie de créer un dossier ou d'en utiliser un existant à la place:

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

Mais je me demande si c'est la bonne façon de le faire? La vérification du code est-elle EEXISTla bonne façon de savoir que le dossier existe déjà? Je sais que je peux faire fs.stat()avant de créer le répertoire, mais ce serait déjà deux coups au système de fichiers.

Deuxièmement, existe-t-il une documentation complète ou au moins plus détaillée de Node.js qui contient des détails sur ce que contiennent les objets d'erreur, quels paramètres signifient, etc.


31
Petit nitpick, mais débarrassez-vous du e &&. En cas d' !eéchec, alors vous savez que ec'est la vérité.
Je déteste paresseux

Réponses:


236

Une bonne façon de faire est d'utiliser le module mkdirp .

$ npm install mkdirp

Utilisez-le pour exécuter la fonction qui nécessite le répertoire. Le rappel est appelé après la création du chemin ou si le chemin existe déjà. L'erreur errest définie si mkdirp n'a pas réussi à créer le chemin du répertoire.

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

    // path exists unless there was an error

});

3
Il me semble que la bonne réponse (lisez «sans dépendance ajoutée») serait celle qui est en bas, par @Raugaral, en utilisant fs.exists(Sync).
Ricardo Pedroni

@meawoppl, c'est 'makedirectory'p. Le «p» est inconnu.
andrew

4
@RicardoPedroni La manière correcte est d'utiliser un module. Les modules essaient généralement de tout cœur de résoudre un problème et sont souvent maintenus. Vous pouvez les mettre à jour facilement avec npm. De plus, vous devez spécifiquement éviter d'utiliser fs.exists [Sync] car son utilisation implique des conditions de concurrence.
1j01 le

16
@ 1j01 Je ne pense pas que la bonne manière soit d'utiliser un module si la plateforme prend en charge nativement l'opération. C'est une route vers le chaos. Je dois admettre qu’il existe de meilleures réponses d’un point de vue technique.
c ..

2
@ 1j01 De plus, l'utilisation des opérations de synchronisation implique des conditions de concurrence car leur utilisation est une résolution pour elles.
c ..

193

Edit: Parce que cette réponse est très populaire, je l'ai mise à jour pour refléter les pratiques à jour.

Nœud> = 10

La nouvelle { recursive: true }option de Node le fspermet désormais de manière native. Cette option imite le comportement d'UNIX mkdir -p. Il s'assurera de manière récursive que chaque partie du chemin existe et ne lèvera pas d'erreur si l'une d'entre elles le fait.

(Remarque: il peut toujours générer des erreurs telles que EPERMou EACCESS, il vaut donc mieux l'envelopper dans un try {} catch (e) {}si votre implémentation y est sensible.)

Version synchrone.

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

Version asynchrone

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

Anciennes versions de Node

En utilisant a try {} catch (err) {}, vous pouvez y parvenir très gracieusement sans rencontrer de condition de concurrence.

Afin d'éviter un temps mort entre la vérification de l'existence et la création du répertoire, nous essayons simplement de le créer directement et de ne pas tenir compte de l'erreur si elle existe EEXIST(le répertoire existe déjà).

Si l'erreur n'est pas EEXIST, cependant, nous devrions lancer une erreur, car nous pourrions avoir affaire à quelque chose comme un EPERMouEACCES

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

Pour mkdir -p-comme le comportement récursif, par exemple ./a/b/c, il faudrait l' appeler sur chaque partie du dirpath, par exemple ./a, ./a/b,.a/b/c


var fs = Npm.require ('fs'); var dir = process.env.PWD + '/ files / users /' + this.userId + '/'; essayez {fs.mkdirSync (dir); } catch (e) {if (e.code! = 'EEXIST') throw e; }
Aaron

J'ai essayé votre code, créez un script js qui utilise la création du catalogue comme ceci: mkdirpSync (path.join (__ dirname, 'first', 'second', 'third', 'ololol', 'works')); Mais j'ai obtenu cette erreur: $ node 1.js fs.js: 747 return binding.mkdir (pathModule._makeLong (path), ^ Error: EPERM, opération non autorisée 'C: \' at Error (native) at Object.fs. mkdirSync (fs.js: 747: 18) à mkdirpSync (C: \ Users \ MAXIM \ Desktop \ test \ 1.js: 15: 8) à Object. <anonyme> (C: \ Users \ MAXIM \ Desktop \ test \ 1.js: 19: 1) ... Pouvez-vous suggérer ce qui ne va pas? Utilisé sur windows évidemment :)
Alendorff

EPERM semble être un problème de permission, donc le script n'aurait pas d'exécution interrompue de toute façon
Christophe Marois

Je pense que ce serait mieux: var mkdirpSync = function (dirpath) {var parts = dirpath.split (path.sep); for (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
avertissement: cela ne fonctionne pas si votre chemin commence par a /
acemtp

62

Si vous voulez une doublure rapide et sale, utilisez ceci:

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


7
fs.existsSync (...) n'est pas obsolète, donc cette réponse semble correcte.
Dan Haywood

La tête haute! Ne fonctionnera pas pour "dir / foo / bar", c'est-à-dire qu'il manque la fonction d'indicateur mkdir -p
Karl Pokus

Cela a également une condition de course
Evert

26

La documentation node.js pour fs.mkdirse réfère essentiellement à la page de manuel Linux pour mkdir(2). Cela indique que cela EEXISTsera également indiqué si le chemin existe mais n'est pas un répertoire qui crée un cas de coin gênant si vous suivez cette route.

Vous feriez peut-être mieux d'appeler fs.statqui vous dira si le chemin existe et s'il s'agit d'un répertoire en un seul appel. Pour (ce que je suppose est) le cas normal où le répertoire existe déjà, ce n'est qu'un seul coup de système de fichiers.

Ces fsméthodes de module sont des enveloppes minces autour des API C natives, vous devez donc consulter les pages de manuel référencées dans la documentation node.js pour plus de détails.


19
Appeler statavant mkdira le potentiel pour une condition de course - gardez cela à l'esprit.
Roger Lipscombe

24

Vous pouvez utiliser ceci:

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. Je ne crois pas que cela fonctionne, statSyncjettera une erreur si l'entité n'existe pas du tout, écrasant le code. Vous devez envelopper cela dans un try/catchbloc.
Chris Foster

2
Désolé, je me trompe. remplacer "statSync" par "existsSync"
Raugaral

5
Selon nodejs.org/api/fs.html#fs_fs_mkdirsync_path_mode, la variante Sync de mkdir n'accepte pas de rappel
danwellman

1
Selon nodejs.org/api/fs.html#fs_fs_existssync_path , fs.existsSync()et fs.exists()sera obsolète.
pau.moreno

7

Je propose une solution sans modules (accumuler des modules n'est jamais recommandé pour la maintenabilité surtout pour les petites fonctions qui peuvent s'écrire en quelques lignes ...):

DERNIÈRE MISE À JOUR :

Dans la v10.12.0, NodeJS implémente les options récursives:

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

METTRE À JOUR :

// 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()est obsolète dans le nœud v9. utiliser à la fs.access()place. (renvoie undefinedsi le fichier existe; sinon génère une erreur ENOENT)
chharvey

Sans aucun package npm, cela fonctionne. C'est un code précieux. Merci
Karthik Sridharan

Celui-ci est bien meilleur pour créer un dossier sous le long chemin existant;) Merci, mec.
Tsung Goh

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

Merci ! Je mets à jour mon message pour aider les autres. Le nœud 10.12.0 était trop récent.
Liberateur


4

Voici le code ES6 que j'utilise pour créer un répertoire (quand il n'existe pas):

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

Remarque:

  • Au début de la createDirectoryfonction, je normalise le chemin pour garantir que le type de séparateur de chemin du système d'exploitation sera utilisé de manière cohérente (par exemple, cela se transformera C:\directory/testen C:\directory\test(sous Windows)
  • fs.existsest obsolète , c'est pourquoi j'utilise fs.statpour vérifier si le répertoire existe déjà
  • Si un répertoire n'existe pas, le code d'erreur sera ENOENT( E rror NO ENT ry)
  • Le répertoire lui-même sera créé en utilisant fs.mkdir
  • Je préfère la fonction asynchrone fs.mkdirà son homologue bloquant fs.mkdirSyncet en raison de l'emballage, Promiseil sera garanti que le chemin du répertoire ne sera retourné qu'une fois le répertoire créé avec succès

Merci pour une solution propre qui n'implique pas de modules inutiles. Cela a parfaitement fonctionné pour moi. J'aimerais qu'il y ait plus de réponses comme celle-ci!
Ken Lyon

3

Vous feriez mieux de ne pas compter les hits du système de fichiers pendant que vous codez en Javascript, à mon avis. Cependant, (1) stat& mkdiret (2) mkdiret vérifiez (ou supprimez) le code d'erreur, les deux méthodes sont bonnes pour faire ce que vous voulez.


-1, je ne vois pas comment la vérification ou la suppression pourraient être les deux bonnes façons de le faire. C'est à peu près une non-réponse.
Matt Ball

C'est un bon moyen de mkdir un répertoire ou d'utiliser un répertoire existant. Je ne vois pas pourquoi tu ne vois pas. La vérification du code d'erreur est une bonne politesse, tandis que l'élimination du code d'erreur est juste une bonne chose. tu n'es pas d'accord?
Chul-Woong Yang

1
C'est peut-être un problème de barrière de la langue, mais je lis cela comme ne répondant tout simplement pas à la question posée par le PO.
Matt Ball

Je vois ce que tu veux dire. Cependant, je crois qu'il existe de nombreuses façons de bien faire les choses. Merci.
Chul-Woong Yang

2

créer un répertoire de noms dynamiques pour chaque utilisateur ... utiliser ce 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");
}

1

Vous pouvez faire tout cela avec le module File System.

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

Vous n'avez même pas besoin de vérifier si le répertoire existe. Le code suivant garantit également que le répertoire existe déjà ou est créé.

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

Réponse de Raugaral mais avec la fonctionnalité -p. Moche, mais ça marche:

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

Tout comme une nouvelle alternative à la réponse de Teemu Ikonen , qui est très simple et facilement lisible, est d'utiliser la ensureDirméthode dufs-extra package.

Il peut non seulement être utilisé comme un remplacement flagrant du fsmodule intégré, mais possède également de nombreuses autres fonctionnalités en plus des fonctionnalités dufs package.

La ensureDirméthode, comme son nom l'indique, garantit que le répertoire existe. Si la structure de répertoires n'existe pas, elle est créée. Commemkdir -p . Pas seulement le dossier final, mais le chemin complet est créé s'il n'existe pas déjà.

celui fourni ci-dessus en est la asyncversion. Il a également une méthode synchrone pour effectuer cela sous la forme de la ensureDirSyncméthode.


0

La réponse de @ Liberateur ci - dessus n'a pas fonctionné pour moi (Node v8.10.0). Une petite modification a fait l'affaire mais je ne suis pas sûr que ce soit une bonne façon. Veuillez suggérer.

// 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');
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.