È questo il modo giusto di creare una directory se non esiste? Dovrebbe avere il permesso completo per la sceneggiatura e leggibile da altri.
var dir = __dirname + '/upload';
if (!path.existsSync(dir)) {
fs.mkdirSync(dir, 0744);
}
È questo il modo giusto di creare una directory se non esiste? Dovrebbe avere il permesso completo per la sceneggiatura e leggibile da altri.
var dir = __dirname + '/upload';
if (!path.existsSync(dir)) {
fs.mkdirSync(dir, 0744);
}
Risposte:
var fs = require('fs');
var dir = './tmp';
if (!fs.existsSync(dir)){
fs.mkdirSync(dir);
}
Syncmetodi è di solito un no-no: non voglio bloccare il ciclo degli eventi
No, per diversi motivi.
Il pathmodulo non ha un metodo exists/ existsSync. È nel fsmodulo. (Forse hai appena fatto un refuso nella tua domanda?)
I documenti ti scoraggiano esplicitamente dall'uso exists.
fs.exists()è un anacronismo ed esiste solo per ragioni storiche. Non dovrebbe esserci quasi mai un motivo per usarlo nel tuo codice.In particolare, controllare se esiste un file prima di aprirlo è un anti-pattern che ti rende vulnerabile alle condizioni di gara: un altro processo può rimuovere il file tra le chiamate a
fs.exists()efs.open(). Basta aprire il file e gestire l'errore quando non è presente.
Dato che stiamo parlando di una directory piuttosto che di un file, questo consiglio implica che dovresti semplicemente chiamare mkdire ignorare incondizionatamente EEXIST.
In generale, dovresti evitare i Syncmetodi * . Stanno bloccando, il che significa che non può succedere nient'altro nel tuo programma mentre vai sul disco. Questa è un'operazione molto costosa e il tempo impiegato interrompe il presupposto fondamentale del ciclo di eventi del nodo.
I Syncmetodi * di solito vanno bene negli script rapidi monouso (quelli che fanno una cosa e poi escono), ma non dovrebbero quasi mai essere usati quando si scrive un server: il server non sarà in grado di rispondere a nessuno per l'intera durata delle richieste I / O. Se più richieste client richiedono operazioni di I / O, il server si arresterà molto rapidamente.
L'unica volta che prenderei in considerazione l'uso dei Syncmetodi * in un'applicazione server è un'operazione che si verifica una volta (e una sola volta), all'avvio. Ad esempio, require utilizza effettivamentereadFileSync per caricare i moduli.
Anche in questo caso, devi comunque fare attenzione perché molti I / O sincroni possono rallentare inutilmente il tempo di avvio del tuo server.
Invece, è necessario utilizzare i metodi I / O asincroni.
Quindi se mettiamo insieme quei consigli, otteniamo qualcosa del genere:
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
});
}
E possiamo usarlo in questo modo:
ensureExists(__dirname + '/upload', 0744, function(err) {
if (err) // handle folder creation error
else // we're all good
});
Naturalmente, questo non tiene conto di casi limite come
0744 == 484.
Ho trovato e modulo npm che funziona come un fascino per questo. È semplicemente fare un mkdir ricorsivamente quando necessario, come un "mkdir -p".
Il mkdirmetodo ha la capacità di creare ricorsivamente qualsiasi directory in un percorso che non esiste e di ignorare quelle che lo fanno.
Dai documenti Node v10 / 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;
});
NOTA: devi prima importare il fsmodulo integrato.
Ora ecco un esempio un po 'più robusto che sfrutta i moduli ES nativi (con flag abilitato ed estensione .mjs), gestisce percorsi non root e tiene conto di percorsi completi:
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');
}
});
}
Puoi usarlo come createDirectories('/components/widget/widget.js');.
E ovviamente, probabilmente vorrai essere più fantasioso usando le promesse con asincrono / attendi per sfruttare la creazione di file in un modo più leggibile in modo sincrono quando vengono create le directory; ma questo va oltre lo scopo della domanda.
Nel caso qualcuno fosse interessato alla versione a una riga. :)
//or in typescript: import * as fs from 'fs';
const fs = require('fs');
!fs.existsSync(dir) && fs.mkdirSync(dir);
Puoi semplicemente usare mkdire rilevare l'errore se la cartella esiste.
Questo è asincrono (quindi la migliore pratica) e sicuro.
fs.mkdir('/path', err => {
if (err && err.code != 'EEXIST') throw 'up'
.. safely do your stuff here
})
(Facoltativamente aggiungi un secondo argomento con la modalità.)
Altri pensieri:
È possibile utilizzare quindi o attendere utilizzando Promisify nativo .
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() })Puoi creare il tuo metodo di promessa, qualcosa del tipo (non testato):
let mkdirAsync = (path, mode) => new Promise(
(resolve, reject) => mkdir (path, mode,
err => (err && err.code !== 'EEXIST') ? reject(err) : resolve()
)
)Per il controllo sincrono, è possibile utilizzare:
fs.existsSync(path) || fs.mkdirSync(path)Oppure puoi usare una libreria, i due più popolari
mkdir('/path').catch(err => { if (err.code != 'EEXIST') throw err;}).then(myFunc);
!==invece di!=
Con il pacchetto fs-extra puoi farlo con una sola riga :
const fs = require('fs-extra');
const dir = '/tmp/this/path/does/not/exist';
fs.ensureDirSync(dir);
La soluzione migliore sarebbe quella di utilizzare il modulo npm chiamato node-fs-extra . Ha un metodo chiamato mkdirche crea la directory che hai citato. Se si fornisce un lungo percorso di directory, verranno create automaticamente le cartelle principali. Il modulo è un super set di moduli npm fs, quindi puoi usare tutte le funzioni fsanche se aggiungi questo modulo.
var dir = 'path/to/dir';
try {
fs.mkdirSync(dir);
} catch(e) {
if (e.code != 'EEXIST') throw e;
}
fs.exists()è obsoleto, ma fs.existsSync()non lo è. Potresti aggiungere un link a una risorsa dicendo che fs.existsSync()è ammortizzato?
Apr 2018: nodejs.org/api/fs.html#fs_fs_existssync_path
var filessystem = require('fs');
var dir = './path/subpath/';
if (!filessystem.existsSync(dir)){
filessystem.mkdirSync(dir);
}else
{
console.log("Directory already exist");
}
Questo può aiutarti :)
ENOENT: nessun file o directory
Soluzione
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 })
Vorrei aggiungere un refattore Promessa dattiloscritto della risposta di josh3736 .
Fa la stessa cosa e ha gli stessi casi limite, capita solo di usare Promesse, dattiloscritti dattiloscritti e funziona con "usa rigoroso".
// 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
}
});
});
}
Con Nodo 10 + ES6:
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;
}
}
})();
È possibile utilizzare il comando fs.stat del file system del nodo per verificare l'esistenza di dir e fs.mkdir per creare una directory con callback oppure fs.mkdirSync per creare una directory senza callback, come in questo esempio:
//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);
}
});
};
Ecco una piccola funzione per creare ricorsivamente directory:
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
}, '')
}
Usando async / await:
const mkdirP = async (directory) => {
try {
return await fs.mkdirAsync(directory);
} catch (error) {
if (error.code != 'EEXIST') {
throw e;
}
}
};
Dovrai promettere fs:
import nodeFs from 'fs';
import bluebird from 'bluebird';
const fs = bluebird.promisifyAll(nodeFs);