Est-ce la bonne façon de créer un répertoire s'il n'existe pas? Il devrait avoir une permission complète pour le script et lisible par d'autres.
var dir = __dirname + '/upload';
if (!path.existsSync(dir)) {
fs.mkdirSync(dir, 0744);
}
var fs = require('fs');
var dir = './tmp';
if (!fs.existsSync(dir)){
fs.mkdirSync(dir);
}
Non, pour plusieurs raisons.
Le module path
n'a pas de méthode exists
/existsSync
. C'est dans le fs
module. (Peut-être que vous venez de faire une faute de frappe dans votre question?)
Les documents vous déconseillent explicitement d'utiliser exists
.
fs.exists()
est un anachronisme et n'existe que pour des raisons historiques. Il ne devrait presque jamais y avoir de raison de l’utiliser dans votre propre code.En particulier, vérifier si un fichier existe avant de l'ouvrir est un anti-motif qui vous rend vulnérable aux conditions de concurrence: un autre processus peut supprimer le fichier entre les appels à
fs.exists()
etfs.open()
. Il suffit d'ouvrir le fichier et de gérer l'erreur quand il n'y en a pas.
Comme nous parlons d'un répertoire plutôt que d'un fichier, ce conseil implique que vous devez simplement appeler inconditionnellement mkdir
et ignorer EEXIST
.
En général, vous devriez éviter les méthodes * Sync
. Ils bloquent, ce qui signifie absolument que rien d’autre dans votre programme ne peut arriver pendant que vous allez sur le disque. Il s’agit d’une opération très coûteuse et le temps qu’il prend brise l’hypothèse de base de la boucle d’événements du noeud.
Les méthodes * Sync
sont généralement bien dans les scripts rapides à usage unique (ceux qui font une chose, puis se terminent), mais ne devraient presque jamais être utilisées lorsque vous écrivez un serveur: votre serveur sera incapable de répondre à qui que ce soit pendant toute la durée des demandes d'E/S. Si plusieurs demandes de client nécessitent des opérations d'E/S, votre serveur s'arrête très rapidement.
La seule fois où j'envisagerais d'utiliser les méthodes * Sync
dans une application serveur est une opération qui se produit une fois (et une seule fois), au démarrage. Par exemple, require
tilise en réalité readFileSync
pour charger des modules.
Même dans ce cas, vous devez rester prudent, car de nombreuses E/S synchrones peuvent ralentir inutilement le temps de démarrage de votre serveur.
Au lieu de cela, vous devez utiliser les méthodes d'E/S asynchrones.
Donc, si nous mettons ensemble ces conseils, nous obtenons quelque chose comme ceci:
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
});
}
Et on peut l'utiliser comme ça:
ensureExists(__dirname + '/upload', 0744, function(err) {
if (err) // handle folder creation error
else // we're all good
});
Bien sûr, cela ne représente pas les cas Edge comme
J'ai trouvé et npm module qui fonctionne comme un charme pour cela. Il suffit simplement de faire un mkdir récursif en cas de besoin, comme un "mkdir -p".
Juste au cas où quelqu'un serait intéressé par la version en une ligne. :)
//or in TypeScript: import * as fs from 'fs';
const fs = require('fs');
!fs.existsSync(dir) && fs.mkdirSync(dir);
Vous pouvez simplement utiliser mkdir
et récupérer l'erreur si le dossier existe.
Ceci est asynchrone (donc meilleure pratique) et sûr.
fs.mkdir('/path', err => {
if (err && err.code != 'EEXIST') throw 'up'
.. safely do your stuff here
})
(Ajoutez éventuellement un deuxième argument avec le mode.)
D'autres pensées:
Vous pouvez alors utiliser ou attendre en utilisant native promisify .
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() })
Vous pouvez créer votre propre méthode de promesse, quelque chose comme (non testé):
let mkdirAsync = (path, mode) => new Promise(
(resolve, reject) => mkdir (path, mode,
err => (err && err.code !== 'EEXIST') ? reject(err) : resolve()
)
)
Pour la vérification synchrone, vous pouvez utiliser:
fs.existsSync(path) || fs.mkdirSync(path)
Ou vous pouvez utiliser une bibliothèque, les deux plus populaires étant
La méthode mkdir
a la capacité de créer récursivement tous les répertoires d’un chemin qui n’existent pas et d’ignorer ceux qui existent.
À partir de la documentation sur les nœuds 10/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;
});
REMARQUE: vous devez d'abord importer le module intégré fs
.
Voici maintenant un exemple un peu plus robuste qui exploite les modules ES natifs (avec l'indicateur activé et l'extension .mjs), gère les chemins d'accès non racine et les comptes de chemins d'accès complets:
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');
}
});
}
Vous pouvez l'utiliser comme createDirectories('/components/widget/widget.js');
.
Et bien sûr, vous souhaiterez probablement obtenir plus de fantaisie en utilisant des promesses avec async/wait pour exploiter la création de fichier de manière plus lisible de manière synchrone lors de la création des répertoires; mais, cela dépasse la portée de la question.
La meilleure solution consisterait à utiliser le module npm appelé node-fs-extra . Il a une méthode appelée mkdir
qui crée le répertoire que vous avez mentionné. Si vous indiquez un chemin de répertoire long, les dossiers parent seront automatiquement créés. Le module est un super ensemble de npm module fs
, vous pouvez donc utiliser toutes les fonctions de fs
également si vous ajoutez ce module.
Avec le package fs-extra , vous pouvez le faire avec n one-liner :
const fs = require('fs-extra');
const dir = '/tmp/this/path/does/not/exist';
fs.ensureDirSync(dir);
var dir = 'path/to/dir';
try {
fs.mkdirSync(dir);
} catch(e) {
if (e.code ~= 'EEXIST') throw e;
}
Je voudrais ajouter un refactor TypeScript Promise de réponse de josh3736 .
Il fait la même chose et a les mêmes cas Edge, il arrive juste d'utiliser Promises, les typedefs TypeScript et fonctionne avec "use strict".
// 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
}
});
});
}
var filessystem = require('fs');
var dir = './path/subpath/';
if (!filessystem.existsSync(dir)){
filessystem.mkdirSync(dir);
}else
{
console.log("Directory already exist");
}
Cela peut vous aider :)
Vous pouvez utiliser node Système de fichiers commande fs.stat pour vérifier si dir existe et fs.mkdir pour créer un répertoire avec rappel, ou fs.mkdirSync pour créer un répertoire sans rappel, comme dans l'exemple suivant:
//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);
}
});
};
Voici une petite fonction pour créer de manière récurrente des répertoires:
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
}, '')
}
ENOENT: aucun fichier ou répertoire de ce type, mkdir './assets/
Solution
// const fs = require('fs') in javascript
// import * as fs from "fs" in TypeScript
// import fs from "fs" in TypeScript
!fs.existsSync(`./assets/`) && fs.mkdirSync(`./assets/`, { recursive: true })
Utiliser async/wait:
const mkdirP = async (directory) => {
try {
return await fs.mkdirAsync(directory);
} catch (error) {
if (error.code != 'EEXIST') {
throw e;
}
}
};
Vous aurez besoin de promisify fs
:
import nodeFs from 'fs';
import bluebird from 'bluebird';
const fs = bluebird.promisifyAll(nodeFs);