Si está realizando esta operación en el arranque o la inicialización de la aplicación, entonces está bien bloquear la ejecución, ya que haría lo mismo si fuera asíncrono. Si está haciendo un directorio como una operación recurrente, entonces es una mala práctica, pero probablemente no causará ningún problema de rendimiento, pero no obstante es un mal hábito. Úselo solo para arrancar su aplicación o para operaciones de una sola vez.
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()y fs.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 mkdire ignorar incondicionalmente EEXIST.
En general, debe evitar los Syncmé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 Syncmé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 Syncmé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 requirerealidad 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 existselse 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 errorelse// we're all good});
Por supuesto, esto no tiene en cuenta los casos extremos como
¿Qué sucede si la carpeta se elimina mientras se ejecuta el programa? (suponiendo que solo verifique que existe una vez durante el inicio)
¿Qué sucede si la carpeta ya existe pero tiene los permisos incorrectos?
¿Esta bandera de "máscara" sigue siendo relevante en 2019? ¿Cuál fue el propósito de esto?
oldboy
Es el modo de archivo Unix : los permisos de lectura / escritura del directorio.
josh3736
44
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".
// 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: fsPrimero 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.
¡Qué respuesta tan subestimada! fs-extra se ha convertido en algo imprescindible para mí. Creo que es una aberración escribir más de 10 líneas para verificar si existe una carpeta ...
538ROMEO
10
La mejor solución sería usar el módulo npm llamado node-fs-extra . Tiene un método llamado mkdirque 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 fstambién si agrega este módulo.
Para Node.js v7.4.0, la documentación indica que 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?
francis
1
Las respuestas de solo código no son muy útiles para los usuarios que vengan a esta pregunta en el futuro. Edite su respuesta para explicar por qué su código resuelve el problema original
¡Gracias! Parece que la función existía en la versión 0.12, quedó en desuso en las versiones 4 y 5 y se restauró en la versión 6 y 7 ... Una especie de función zombi ...
var filessystem = require('fs');var dir ='./path/subpath/';if(!filessystem.existsSync(dir)){
filessystem.mkdirSync(dir);}else{
console.log("Directory already exist");}
const fs = require('fs')// in javascriptimport* as fs from"fs"// in typescriptimport fs from"fs"// in typescript// it will create the directory if it does not exist.!fs.existsSync(`./assets/`)&& fs.mkdirSync(`./assets/`,{ recursive:true})
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 fsconst 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
},'')}
Respuestas:
fuente
Sync
métodos * suele ser un no-no: no quiero bloquear el bucle de eventosNo, por múltiples razones.
El
path
módulo no tiene un métodoexists
/existsSync
. Está en elfs
módulo. (¿Quizás acabas de hacer un error tipográfico en tu pregunta?)Los documentos te desalientan explícitamente de usar
exists
.Como estamos hablando de un directorio en lugar de un archivo, este consejo implica que debe llamar
mkdir
e ignorar incondicionalmenteEEXIST
.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, enrequire
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:
Y podemos usarlo así:
Por supuesto, esto no tiene en cuenta los casos extremos como
fuente
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".
https://www.npmjs.com/package/mkdirp
fuente
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 :
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:
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.
fuente
Por si acaso alguien interesado en la versión de una línea. :)
fuente
Simplemente puede usar
mkdir
y detectar el error si la carpeta existe.Esto es asíncrono (así que las mejores prácticas) y seguro.
(Opcionalmente, agregue un segundo argumento con el modo).
Otros pensamientos:
Podrías usar entonces o esperar usando promisify nativo .
Puede hacer su propio método de promesa, algo como (no probado):
Para la verificación sincrónica, puede usar:
O puedes usar una biblioteca, los dos seres más populares
fuente
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 :
fuente
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 npmfs
, por lo que puede usar todas las funcionesfs
también si agrega este módulo.fuente
fuente
fs.exists()
está en desuso, perofs.existsSync()
no lo está. ¿Podría agregar un enlace a un recurso que diga quefs.existsSync()
está depreciado?Apr 2018
: nodejs.org/api/fs.html#fs_fs_existssync_pathEsto puede ayudarte :)
fuente
Solución
fuente
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".
fuente
Con Nodo 10 + ES6:
fuente
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:
fuente
Aquí hay una pequeña función para crear directorios recursivamente:
fuente
Usando async / await:
Tendrá que prometer
fs
:fuente