node.js - validar - readstream nodejs
¿Cómo crear una ruta completa con el nodo fs.mkdirSync? (20)
Estoy tratando de crear una ruta completa si no existe.
El código se ve así:
var fs = require(''fs'');
if (!fs.existsSync(newDest)) fs.mkdirSync(newDest);
Este código funciona muy bien siempre que haya un solo subdirectorio (un nuevoDest como ''dir1''), sin embargo, cuando hay una ruta de directorio como (''dir1 / dir2'') falla con Error: ENOENT, no existe tal archivo o directorio
Me gustaría poder crear la ruta completa con tan pocas líneas de código como sea necesario.
Leí que hay una opción recursiva en fs y lo intenté así
var fs = require(''fs'');
if (!fs.existsSync(newDest)) fs.mkdirSync(newDest,''0777'', true);
Siento que debería ser así de simple crear recursivamente un directorio que no existe. ¿Me estoy perdiendo algo o necesito analizar la ruta y verificar cada directorio y crearlo si aún no existe?
Soy bastante nuevo en Node. Tal vez estoy usando una versión anterior de FS?
¿Qué tal este enfoque:
if (!fs.existsSync(pathToFile)) {
var dirName = "";
var filePathSplit = pathToFile.split(''/'');
for (var index = 0; index < filePathSplit.length; index++) {
dirName += filePathSplit[index]+''/'';
if (!fs.existsSync(dirName))
fs.mkdirSync(dirName);
}
}
Esto funciona para la ruta relativa.
Ahora con NodeJS> =
10.12.0
, puede usar
fs.mkdirSync(path, { recursive: true })
fs.mkdirSync
Aquí está mi versión imprescindible de
mkdirp
para nodejs.
function mkdirSyncP(location) {
let normalizedPath = path.normalize(location);
let parsedPathObj = path.parse(normalizedPath);
let curDir = parsedPathObj.root;
let folders = parsedPathObj.dir.split(path.sep);
folders.push(parsedPathObj.base);
for(let part of folders) {
curDir = path.join(curDir, part);
if (!fs.existsSync(curDir)) {
fs.mkdirSync(curDir);
}
}
}
Basado en la cero dependencias de , aquí hay una variante de un poco más amigable para principiantes, como módulo:
import * as fs from ''fs'';
import * as path from ''path'';
/**
* Recursively creates directories until `targetDir` is valid.
* @param targetDir target directory path to be created recursively.
* @param isRelative is the provided `targetDir` a relative path?
*/
export function mkdirRecursiveSync(targetDir: string, isRelative = false) {
const sep = path.sep;
const initDir = path.isAbsolute(targetDir) ? sep : '''';
const baseDir = isRelative ? __dirname : ''.'';
targetDir.split(sep).reduce((prevDirPath, dirToCreate) => {
const curDirPathToCreate = path.resolve(baseDir, prevDirPath, dirToCreate);
try {
fs.mkdirSync(curDirPathToCreate);
} catch (err) {
if (err.code !== ''EEXIST'') {
throw err;
}
// caught EEXIST error if curDirPathToCreate already existed (not a problem for us).
}
return curDirPathToCreate; // becomes prevDirPath on next call to reduce
}, initDir);
}
Demasiadas respuestas, pero aquí hay una solución sin recurrencia que funciona dividiendo el camino y luego volviendo a construirlo de izquierda a derecha
function mkdirRecursiveSync(path) {
let paths = path.split(path.delimiter);
let fullPath = '''';
paths.forEach((path) => {
if (fullPath === '''') {
fullPath = path;
} else {
fullPath = fullPath + ''/'' + path;
}
if (!fs.existsSync(fullPath)) {
fs.mkdirSync(fullPath);
}
});
};
Para aquellos preocupados por la compatibilidad entre Windows y Linux, simplemente reemplace la barra diagonal con doble barra diagonal inversa ''/' en los dos casos anteriores, pero TBH estamos hablando de nodo fs no de línea de comando de Windows y el primero es bastante indulgente y el código anterior simplemente funcionará en Windows y es más una solución completa multiplataforma.
Ejemplo para Windows (sin dependencias adicionales y manejo de errores)
const path = require(''path'');
const fs = require(''fs'');
let dir = "C://temp//dir1//dir2//dir3";
function createDirRecursively(dir) {
if (!fs.existsSync(dir)) {
createDirRecursively(path.join(dir, ".."));
fs.mkdirSync(dir);
}
}
createDirRecursively(dir); //creates dir1/dir2/dir3 in C:/temp
Esta característica se ha agregado a node.js en la versión 10.12.0, por lo que es tan fácil como pasar una opción
{recursive: true}
como segundo argumento para la llamada
fs.mkdir()
.
Vea el
ejemplo en los documentos oficiales
.
No necesita módulos externos ni su propia implementación.
Esta versión funciona mejor en Windows que la respuesta principal porque comprende ambos
/
y
path.sep
para que las barras diagonales funcionen en Windows como deberían.
Admite rutas absolutas y relativas (relativas al
process.cwd
).
/**
* Creates a folder and if necessary, parent folders also. Returns true
* if any folders were created. Understands both ''/'' and path.sep as
* path separators. Doesn''t try to create folders that already exist,
* which could cause a permissions error. Gracefully handles the race
* condition if two processes are creating a folder. Throws on error.
* @param targetDir Name of folder to create
*/
export function mkdirSyncRecursive(targetDir) {
if (!fs.existsSync(targetDir)) {
for (var i = targetDir.length-2; i >= 0; i--) {
if (targetDir.charAt(i) == ''/'' || targetDir.charAt(i) == path.sep) {
mkdirSyncRecursive(targetDir.slice(0, i));
break;
}
}
try {
fs.mkdirSync(targetDir);
return true;
} catch (err) {
if (err.code !== ''EEXIST'') throw err;
}
}
return false;
}
Exec puede ser desordenado en Windows. Hay una solución más "nodie". Básicamente, tiene una llamada recursiva para ver si existe un directorio y sumergirse en el elemento secundario (si existe) o crearlo. Aquí hay una función que creará los hijos y llamará a una función cuando termine:
fs = require(''fs'');
makedirs = function(path, func) {
var pth = path.replace(/[''//]+/g, ''/'');
var els = pth.split(''/'');
var all = "";
(function insertOne() {
var el = els.splice(0, 1)[0];
if (!fs.existsSync(all + el)) {
fs.mkdirSync(all + el);
}
all += el + "/";
if (els.length == 0) {
func();
} else {
insertOne();
}
})();
}
Puedes usar la siguiente función
const recursiveUpload = (ruta: cadena) => {rutas const = ruta.split ("/")
const fullPath = paths.reduce((accumulator, current) => {
fs.mkdirSync(accumulator)
return `${accumulator}/${current}`
})
fs.mkdirSync(fullPath)
return fullPath
}
Entonces, qué hace:
-
Cree
paths
variables, donde almacena cada ruta por sí misma como un elemento de la matriz. - Agrega "/" al final de cada elemento en la matriz.
-
Hace para el ciclo:
- Crea un directorio a partir de la concatenación de elementos de matriz cuyos índices son de 0 a la iteración actual. Básicamente, es recursivo.
¡Espero que ayude!
Por cierto, en el Nodo v10.12.0 puede usar la creación de rutas recursivas dándola como argumento adicional.
fs.mkdir(''/tmp/a/apple'', { recursive: true }, (err) => { if (err) throw err; });
Sé que esta es una pregunta antigua, pero nodejs v10.12.0 ahora admite esto de forma nativa con la opción
recursive
establecida en verdadero.
fs.mkdir
// Creates /tmp/a/apple, regardless of whether `/tmp` and /tmp/a exist.
fs.mkdir(''/tmp/a/apple'', { recursive: true }, (err) => {
if (err) throw err;
});
Simplemente puede verificar que la carpeta exista o no en la ruta de forma recursiva y crear la carpeta mientras verifica si no están presentes. ( SIN BIBLIOTECA EXTERNA )
function checkAndCreateDestinationPath (fileDestination) {
const dirPath = fileDestination.split(''/'');
dirPath.forEach((element, index) => {
if(!fs.existsSync(dirPath.slice(0, index + 1).join(''/''))){
fs.mkdirSync(dirPath.slice(0, index + 1).join(''/''));
}
});
}
Tan limpio como esto :)
function makedir(fullpath) {
let destination_split = fullpath.replace(''/'', ''//').split(''//')
let path_builder = destination_split[0]
$.each(destination_split, function (i, path_segment) {
if (i < 1) return true
path_builder += ''//' + path_segment
if (!fs.existsSync(path_builder)) {
fs.mkdirSync(path_builder)
}
})
}
Una forma asincrónica de crear directorios de forma recursiva:
import fs from ''fs''
const mkdirRecursive = function(path, callback) {
let controlledPaths = []
let paths = path.split(
''/'' // Put each path in an array
).filter(
p => p != ''.'' // Skip root path indicator (.)
).reduce((memo, item) => {
// Previous item prepended to each item so we preserve realpaths
const prevItem = memo.length > 0 ? memo.join(''/'').replace(//.///g, '''')+''/'' : ''''
controlledPaths.push(''./''+prevItem+item)
return [...memo, ''./''+prevItem+item]
}, []).map(dir => {
fs.mkdir(dir, err => {
if (err && err.code != ''EEXIST'') throw err
// Delete created directory (or skipped) from controlledPath
controlledPaths.splice(controlledPaths.indexOf(dir), 1)
if (controlledPaths.length === 0) {
return callback()
}
})
})
}
// Usage
mkdirRecursive(''./photos/recent'', () => {
console.log(''Directories created succesfully!'')
})
Una opción es usar el módulo shelljs
npm install shelljs
var shell = require(''shelljs'');
shell.mkdir(''-p'', fullPath);
Desde esa página:
Opciones Disponibles:
p: ruta completa (creará directorios intermedios si es necesario)
Como otros han notado, hay otros módulos más enfocados. Pero, fuera de mkdirp, tiene toneladas de otras operaciones de shell útiles (como cuál, grep, etc.) y funciona en Windows y * nix
Una respuesta más robusta es usar use mkdirp .
var mkdirp = require(''mkdirp'');
mkdirp(''/path/to/dir'', function (err) {
if (err) console.error(err)
else console.log(''dir created'')
});
Luego proceda a escribir el archivo en la ruta completa con:
fs.writeFile (''/path/to/dir/file.dat''....
Usando reduce podemos verificar si cada ruta existe y crearla si es necesario, también de esta manera creo que es más fácil de seguir. Editado, gracias @Arvin, deberíamos usar path.sep para obtener el separador de segmento de ruta específico de la plataforma adecuada.
const path = require(''path'');
// Path separators could change depending on the platform
const pathToCreate = ''path/to/dir'';
pathToCreate
.split(path.sep)
.reduce((prevPath, folder) => {
const currentPath = path.join(prevPath, folder, path.sep);
if (!fs.existsSync(currentPath)){
fs.mkdirSync(currentPath);
}
return currentPath;
}, '''');
fs-extra agrega métodos del sistema de archivos que no están incluidos en el módulo fs nativo. Es una caída en el reemplazo de fs.
Instalar
fs-extra
$ npm install --save fs-extra
const fs = require("fs-extra");
// Make sure the output directory is there.
fs.ensureDirSync(newDest);
Hay opciones de sincronización y asíncrona.
https://github.com/jprichardson/node-fs-extra/blob/master/docs/ensureDir.md
Editar
NodeJS versión
10.12.0
ha agregado un soporte nativo para
mkdir
y
mkdirSync
para crear un directorio recursivamente con la opción
recursive: true
como la siguiente:
fs.mkdirSync(targetDir, { recursive: true });
Y si prefiere la
fs Promises API
, puede escribir
fs.promises.mkdir(targetDir, { recursive: true });
Respuesta original
¡Cree directorios de forma recursiva si no existen! ( Cero dependencias )
const fs = require(''fs'');
const path = require(''path'');
function mkDirByPathSync(targetDir, { isRelativeToScript = false } = {}) {
const sep = path.sep;
const initDir = path.isAbsolute(targetDir) ? sep : '''';
const baseDir = isRelativeToScript ? __dirname : ''.'';
return targetDir.split(sep).reduce((parentDir, childDir) => {
const curDir = path.resolve(baseDir, parentDir, childDir);
try {
fs.mkdirSync(curDir);
} catch (err) {
if (err.code === ''EEXIST'') { // curDir already exists!
return curDir;
}
// To avoid `EISDIR` error on Mac and `EACCES`-->`ENOENT` and `EPERM` on Windows.
if (err.code === ''ENOENT'') { // Throw the original parentDir error on curDir `ENOENT` failure.
throw new Error(`EACCES: permission denied, mkdir ''${parentDir}''`);
}
const caughtErr = [''EACCES'', ''EPERM'', ''EISDIR''].indexOf(err.code) > -1;
if (!caughtErr || caughtErr && curDir === path.resolve(targetDir)) {
throw err; // Throw if it''s just the last created dir.
}
}
return curDir;
}, initDir);
}
Uso
// Default, make directories relative to current working directory.
mkDirByPathSync(''path/to/dir'');
// Make directories relative to the current script.
mkDirByPathSync(''path/to/dir'', {isRelativeToScript: true});
// Make directories with an absolute path.
mkDirByPathSync(''/path/to/dir'');
Manifestación
Explicaciones
-
[ACTUALIZACIÓN]
Esta solución maneja errores específicos de la plataforma como
EISDIR
para Mac yEPERM
yEACCES
para Windows. Gracias a todos los comentarios de informes de @PediT., @JohnQ, @ deed02392, @robyoder y @Almenon. - Esta solución maneja las rutas relativas y absolutas . Gracias al comentario de @john.
-
En el caso de rutas relativas, los directorios de destino se crearán (resolverán) en el directorio de trabajo actual.
Para resolverlos en relación con el directorio de script actual, pase
{isRelativeToScript: true}
. -
Usando
path.sep
ypath.resolve()
, no solo/
concatenación, para evitar problemas multiplataforma. -
Usando
fs.mkdirSync
y manejando el error contry/catch
si se lanza para manejar condiciones de carrera: otro proceso puede agregar el archivo entre las llamadas afs.existsSync()
y fs.mkdirSync y causa una excepción.-
La otra forma de lograrlo podría ser verificar si existe un archivo y luego crearlo, es decir,
if (!fs.existsSync(curDir) fs.mkdirSync(curDir);
Pero este es un antipatrón que deja el código vulnerable a la raza condiciones Gracias al comentario de @GershomMaes sobre la verificación de existencia del directorio.
-
La otra forma de lograrlo podría ser verificar si existe un archivo y luego crearlo, es decir,
- Requiere Nodo v6 y posterior para soportar la desestructuración. (Si tiene problemas para implementar esta solución con versiones antiguas de Node, solo déjeme un comentario)
const fs = require(''fs'');
try {
fs.mkdirSync(path, { recursive: true });
} catch (error) {
// this make script keep running, even when folder already exist
console.log(error);
}