J'essaie de créer un chemin complet s'il n'existe pas.
Le code ressemble à ceci:
var fs = require('fs');
if (!fs.existsSync(newDest)) fs.mkdirSync(newDest);
Ce code fonctionne très bien tant qu'il n'y a qu'un seul sous-répertoire (un newDest comme 'dir1'). Cependant, lorsqu'il existe un chemin de répertoire du type ('dir1/dir2'), il échoue avec Erreur: ENOENT, aucun fichier de ce type ou répertoire
J'aimerais pouvoir créer le chemin complet avec aussi peu de lignes de code que nécessaire.
J'ai lu qu'il y avait une option récursive sur fs et je l'ai essayé comme ça
var fs = require('fs');
if (!fs.existsSync(newDest)) fs.mkdirSync(newDest,'0777', true);
Je pense qu'il devrait être aussi simple de créer récursivement un répertoire qui n'existe pas. Est-ce que quelque chose me manque ou dois-je analyser le chemin, vérifier chaque répertoire et le créer s'il n'existe pas déjà?
Je suis assez nouveau pour Node. J'utilise peut-être une ancienne version de FS?
Une option consiste à utiliser shelljs module
npm installer shelljs
var Shell = require('shelljs');
Shell.mkdir('-p', fullPath);
De cette page:
Options disponibles:
p: chemin complet (créera des répertoires intermédiaires si nécessaire)
Comme d'autres l'ont noté, il existe d'autres modules plus ciblés. Mais, en dehors de mkdirp, il a des tonnes d’autres opérations Shell utiles (comme grep, etc.) et fonctionne avec windows et * nix
Modifier
NodeJS version 10 a ajouté une prise en charge native de mkdir
et mkdirSync
afin de créer un répertoire de manière récursive avec l'option recursive: true
comme suit:
fs.mkdirSync(targetDir, { recursive: true });
Et si vous préférez fs Promises API
, vous pouvez écrire
fs.promises.mkdir(targetDir, {recursive: true});
Créez des répertoires de manière récursive s'ils n'existent pas! (Zero dependencies)
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);
}
// 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');
EISDIR
pour Mac et EPERM
et EACCES
pour Windows. Merci à tous les commentaires de @PediT., @JohnQ, @ deed02392, @robyoder et @Almenon.{isRelativeToScript: true}
.path.sep
et path.resolve()
, et pas seulement de la concaténation /
, pour éviter les problèmes multi-plateformes.fs.mkdirSync
et gestion de l'erreur avec try/catch
si le problème est traité: un autre processus peut ajouter le fichier entre les appels à fs.existsSync()
et fs.mkdirSync()
et provoque une exception .if (!fs.existsSync(curDir) fs.mkdirSync(curDir);
. Mais c'est un anti-modèle qui laisse le code vulnérable aux conditions de concurrence. Merci à @GershomMaes de commenter le contrôle d’existence des répertoires.Une réponse plus robuste consiste à utiliser mkdirp .
var mkdirp = require('mkdirp');
mkdirp('/path/to/dir', function (err) {
if (err) console.error(err)
else console.log('dir created')
});
Ensuite, écrivez le fichier dans le chemin complet avec:
fs.writeFile ('/path/to/dir/file.dat'....
fs-extra ajoute des méthodes de système de fichiers non incluses dans le module natif de fs. C'est une baisse de remplacement pour fs.
Installez fs-extra
$ npm install --save fs-extra
const fs = require("fs-extra");
// Make sure the output directory is there.
fs.ensureDirSync(newDest);
Il existe des options de synchronisation et async.
https://github.com/jprichardson/node-fs-extra/blob/master/docs/ensureDir.md
En utilisant reduction, nous pouvons vérifier si chaque chemin existe et le créer si nécessaire. Aussi, de cette façon, je pense que c'est plus facile à suivre. Modifié, merci @Arvin, nous devrions utiliser path.sep pour obtenir le séparateur de segment de chemin spécifique à la plate-forme.
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;
}, '');
Cette fonctionnalité a été ajoutée à node.js dans la version 10.12.0, aussi simple que de passer une option {recursive: true}
comme second argument à l'appel fs.mkdir()
. Voir l'exemple dans la documentation officielle .
Pas besoin de modules externes ou de votre propre implémentation.
je sais que c’est une vieille question, mais nodejs v10.12 le prend désormais en charge de manière native avec l’option recursive
définie sur true. 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;
});
Vous pouvez utiliser la fonction suivante
const recursiveUpload = (chemin: chaîne) => { const path = path.split ("/")
const fullPath = paths.reduce((accumulator, current) => {
fs.mkdirSync(accumulator)
return `${accumulator}/${current}`
})
fs.mkdirSync(fullPath)
return fullPath
}
Alors qu'est-ce qu'il fait:
paths
, où elle stocke chaque chemin par lui-même en tant qu'élément du tableau.J'espère que cela pourra aider!
En passant, dans Node 10.12.0, vous pouvez utiliser la création de chemin récursif en le donnant comme argument supplémentaire.
fs.mkdir('/tmp/a/Apple', { recursive: true }, (err) => {
if (err) throw err;
});
Trop de réponses, mais voici une solution sans récursivité qui fonctionne en scindant le chemin puis en le reconstruisant de gauche à droite
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);
}
});
};
Pour ceux qui s'inquiètent de la compatibilité Windows vs Linux, il suffit de remplacer la barre oblique par une double barre oblique inversée '\' dans les deux occurrences ci-dessus, mais TBH concerne le noeud fs et non la ligne de commande Windows. fonctionnera simplement sous Windows et constituera davantage une solution complète multiplateforme.
Exemple pour Windows (pas de dépendances supplémentaires et traitement des erreurs)
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
Maintenant avec NodeJS> = 10, vous pouvez utiliser fs.mkdirSync(path, { recursive: true })
fs.mkdirSync
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);
}
Sur la base de la réponse de mouneer zéro-dependencies, voici une variante TypeScript
légèrement plus conviviale pour les débutants, sous forme de module:
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);
}
Vous pouvez simplement vérifier que le dossier existe ou non dans le chemin d'accès de manière récursive et créer le dossier au fur et à mesure que vous vérifiez s'il est absent. ( PAS DE BIBLIOTHEQUE EXTERNE )
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('/'));
}
});
}
Voici ma version impérative de mkdirp
pour 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);
}
}
}
Une manière asynchrone de créer des répertoires de manière récursive:
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!')
})
Que diriez-vous de cette approche:
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);
}
}
Cela fonctionne pour le chemin relatif.
Aussi propre que ça :)
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)
}
})
}