¿Es esta la forma correcta de crear un directorio si no existe? Debe tener permiso completo para el guión y que otros puedan leerlo.
var dir = __dirname + '/upload';
if (!path.existsSync(dir)) {
fs.mkdirSync(dir, 0744);
}
¿Es esta la forma correcta de crear un directorio si no existe? Debe tener permiso completo para el guión y que otros puedan leerlo.
var dir = __dirname + '/upload';
if (!path.existsSync(dir)) {
fs.mkdirSync(dir, 0744);
}
Respuestas:
var fs = require('fs');
var dir = './tmp';
if (!fs.existsSync(dir)){
fs.mkdirSync(dir);
}
Sync
métodos * suele ser un no-no: no quiero bloquear el bucle de eventos
No, por múltiples razones.
El path
módulo no tiene un método exists
/ existsSync
. Está en el fs
módulo. (¿Quizás acabas de hacer un error tipográfico en tu pregunta?)
Los documentos te desalientan explícitamente de usar exists
.
fs.exists()
es un anacronismo y existe solo por razones históricas. Casi nunca debería haber una razón para usarlo en su propio código.En particular, verificar si existe un archivo antes de abrirlo es un antipatrón que lo deja vulnerable a las condiciones de carrera: otro proceso puede eliminar el archivo entre las llamadas a
fs.exists()
yfs.open()
. Simplemente abra el archivo y maneje el error cuando no esté allí.
Como estamos hablando de un directorio en lugar de un archivo, este consejo implica que debe llamar mkdir
e ignorar incondicionalmente EEXIST
.
En general, debe evitar los Sync
métodos * . Están bloqueando, lo que significa que nada más en su programa puede suceder mientras va al disco. Esta es una operación muy costosa, y el tiempo que toma rompe el supuesto central del bucle de eventos del nodo.
Los Sync
métodos * generalmente están bien en scripts rápidos de un solo propósito (aquellos que hacen una cosa y luego salen), pero casi nunca se deben usar cuando está escribiendo un servidor: su servidor no podrá responder a nadie durante toda la duración de las solicitudes de E / S. Si varias solicitudes de clientes requieren operaciones de E / S, su servidor se detendrá rápidamente.
La única vez que consideraría usar Sync
métodos * en una aplicación de servidor es en una operación que ocurre una vez (y solo una vez), al inicio. Por ejemplo, en require
realidad se usareadFileSync
para cargar módulos.
Incluso entonces, debe tener cuidado porque muchas E / S sincrónicas pueden ralentizar innecesariamente el tiempo de inicio de su servidor.
En su lugar, debe usar los métodos de E / S asíncronas.
Entonces, si juntamos esos consejos, obtenemos algo como esto:
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
});
}
Y podemos usarlo así:
ensureExists(__dirname + '/upload', 0744, function(err) {
if (err) // handle folder creation error
else // we're all good
});
Por supuesto, esto no tiene en cuenta los casos extremos como
0744 == 484
.
He encontrado un módulo npm que funciona de maravilla para esto. Es simplemente hacer un mkdir recursivamente cuando sea necesario, como un "mkdir -p".
El mkdir
método tiene la capacidad de crear recursivamente cualquier directorio en una ruta que no exista e ignorar los que sí existen.
Desde el Nodo v10 / 11 documentos :
// 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: fs
Primero deberá importar el módulo incorporado .
Ahora, aquí hay un ejemplo un poco más robusto que aprovecha los módulos ES nativos (con la marca habilitada y la extensión .mjs), maneja rutas no root y da cuenta de las rutas completas:
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');
}
});
}
Puedes usarlo como createDirectories('/components/widget/widget.js');
.
Y, por supuesto, es probable que desee obtener más fantasía mediante el uso de promesas con async / await para aprovechar la creación de archivos de una manera sincrónica más legible cuando se crean los directorios; pero, eso está más allá del alcance de la pregunta.
Por si acaso alguien interesado en la versión de una línea. :)
//or in typescript: import * as fs from 'fs';
const fs = require('fs');
!fs.existsSync(dir) && fs.mkdirSync(dir);
Simplemente puede usar mkdir
y detectar el error si la carpeta existe.
Esto es asíncrono (así que las mejores prácticas) y seguro.
fs.mkdir('/path', err => {
if (err && err.code != 'EEXIST') throw 'up'
.. safely do your stuff here
})
(Opcionalmente, agregue un segundo argumento con el modo).
Otros pensamientos:
Podrías usar entonces o esperar usando 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() })
Puede hacer su propio método de promesa, algo como (no probado):
let mkdirAsync = (path, mode) => new Promise(
(resolve, reject) => mkdir (path, mode,
err => (err && err.code !== 'EEXIST') ? reject(err) : resolve()
)
)
Para la verificación sincrónica, puede usar:
fs.existsSync(path) || fs.mkdirSync(path)
O puedes usar una biblioteca, los dos seres más populares
mkdir('/path').catch(err => { if (err.code != 'EEXIST') throw err;}).then(myFunc);
!==
lugar de!=
Con el paquete fs-extra puede hacer esto con una sola línea :
const fs = require('fs-extra');
const dir = '/tmp/this/path/does/not/exist';
fs.ensureDirSync(dir);
La mejor solución sería usar el módulo npm llamado node-fs-extra . Tiene un método llamado mkdir
que crea el directorio que mencionaste. Si proporciona una ruta de directorio larga, creará las carpetas principales automáticamente. El módulo es un conjunto súper de módulo npm fs
, por lo que puede usar todas las funciones fs
también si agrega este módulo.
var dir = 'path/to/dir';
try {
fs.mkdirSync(dir);
} catch(e) {
if (e.code != 'EEXIST') throw e;
}
fs.exists()
está en desuso, pero fs.existsSync()
no lo está. ¿Podría agregar un enlace a un recurso que diga que fs.existsSync()
está depreciado?
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");
}
Esto puede ayudarte :)
ENOENT: no existe tal archivo o directorio
Solución
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 })
Me gustaría agregar un refactor de Promesa mecanografiada de la respuesta de josh3736 .
Hace lo mismo y tiene los mismos casos límite, simplemente utiliza Promesas, typedefs typedefs y funciona con "use estricto".
// 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;
}
}
})();
Puede usar el comando del sistema de archivos del nodo fs.stat para verificar si existe el directorio y fs.mkdir para crear un directorio con devolución de llamada, o fs.mkdirSync para crear un directorio sin devolución de llamada, como este ejemplo:
//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);
}
});
};
Aquí hay una pequeña función para crear directorios recursivamente:
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;
}
}
};
Tendrá que prometer fs
:
import nodeFs from 'fs';
import bluebird from 'bluebird';
const fs = bluebird.promisifyAll(nodeFs);