Це правильний спосіб створення каталогу, якщо він не існує. Він повинен мати повний дозвіл на сценарій і читати його іншими.
var dir = __dirname + '/upload';
if (!path.existsSync(dir)) {
fs.mkdirSync(dir, 0744);
}
Це правильний спосіб створення каталогу, якщо він не існує. Він повинен мати повний дозвіл на сценарій і читати його іншими.
var dir = __dirname + '/upload';
if (!path.existsSync(dir)) {
fs.mkdirSync(dir, 0744);
}
Відповіді:
var fs = require('fs');
var dir = './tmp';
if (!fs.existsSync(dir)){
fs.mkdirSync(dir);
}
Syncметодів * зазвичай - ні-ні: не хочуть блокувати цикл подій
Ні, з кількох причин.
pathМодуль не маєexists / existsSyncметоду. Це в fsмодулі. (Можливо, ви щойно зробили помилку на друку у своєму питанні?)
Документи явно заважають вам використовувати exists.
fs.exists()є анахронізмом і існує лише з історичних причин. Майже ніколи не повинно бути причин використовувати його у власному коді.Зокрема, перевірка наявності файлу перед відкриттям - це анти-шаблон, який залишає вас вразливими до перегонових умов: інший процес може видалити файл між викликами до
fs.exists()таfs.open(). Просто відкрийте файл і обробіть помилку, коли його немає.
Оскільки ми говоримо про каталог, а не про файл, ця порада означає, що вам слід просто беззастережно зателефонувати mkdir та ігнорувати EEXIST.
Загалом, вам слід уникати *Sync методів . Вони блокуються, а це означає, що нічого іншого у вашій програмі не може статися під час переходу на диск. Це дуже дорога операція, і час, який потрібно, порушує основне припущення про цикл подій вузла.
Методи *, Syncяк правило, є чудовими у швидких сценаріях, що мають одну ціль (ті, що роблять одне, а потім виходять), але майже ніколи не повинні використовуватися під час написання сервера: ваш сервер не зможе відповісти нікому протягом усієї тривалості запитів вводу / виводу. Якщо для декількох запитів клієнтів потрібні операції вводу / виводу, ваш сервер дуже швидко перемелиться.
Єдиний раз, коли я б розглядав можливість використання * Syncметодів у серверній програмі, це операція, що відбувається один раз (і лише один раз), при запуску. Наприклад, require фактично використовуєreadFileSync для завантаження модулів.
Навіть тоді ви все ще повинні бути обережними, оскільки багато синхронних вводу-виводу можуть зайво уповільнити час запуску вашого сервера.
Натомість слід використовувати асинхронні методи вводу / виводу.
Тож якщо ми з’єднаємо ці поради, отримаємо щось подібне:
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
});
}
І ми можемо використовувати це так:
ensureExists(__dirname + '/upload', 0744, function(err) {
if (err) // handle folder creation error
else // we're all good
});
Звичайно, це не враховує таких крайових випадків
0744 == 484.
Я знайшов і npm модуль, який працює як шарм для цього. Це просто робити рекурсивно mkdir при необхідності, як "mkdir -p".
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;
});
ПРИМІТКА. Вам потрібно буде імпортувати вбудований модуль fs . Спочатку модуль.
Тепер ось трохи більш надійний приклад, який використовує нативні модулі ES (з увімкненим прапором та розширенням .mjs), обробляє некорінні шляхи та облікові записи для повних імен:
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');
}
});
}
Ви можете використовувати його як createDirectories('/components/widget/widget.js');.
І звичайно, ви, мабуть, захочете отримати більше фантазії, використовуючи обіцянки з async / очікуючи, щоб скористатися створенням файлів більш читаним синхронним виглядом, коли створюються каталоги; але це виходить за межі питання.
Про всяк випадок, коли хтось зацікавлений у версії однієї лінії. :)
//or in typescript: import * as fs from 'fs';
const fs = require('fs');
!fs.existsSync(dir) && fs.mkdirSync(dir);
Ви можете просто скористатися mkdirпомилкою, якщо папка існує.
Це асинхроніка (так найкраща практика) і безпечна.
fs.mkdir('/path', err => {
if (err && err.code != 'EEXIST') throw 'up'
.. safely do your stuff here
})
(За бажанням додайте другий аргумент із режимом.)
Інші думки:
Ви можете користуватися тоді або чекати, використовуючи нативні пропіси .
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() })Ви можете зробити власний метод обіцянки, на кшталт (неперевірений):
let mkdirAsync = (path, mode) => new Promise(
(resolve, reject) => mkdir (path, mode,
err => (err && err.code !== 'EEXIST') ? reject(err) : resolve()
)
)Для синхронної перевірки ви можете використовувати:
fs.existsSync(path) || fs.mkdirSync(path)Або ви можете використовувати бібліотеку, дві найпопулярніші
mkdir('/path').catch(err => { if (err.code != 'EEXIST') throw err;}).then(myFunc);
!==замість!=
За допомогою пакета fs-extra ви можете це зробити за допомогою одноклайничного :
const fs = require('fs-extra');
const dir = '/tmp/this/path/does/not/exist';
fs.ensureDirSync(dir);
Найкращим рішенням буде використання модуля npm під назвою node-fs-extra . Він має метод, mkdirякий називається, який створює згаданий вами каталог. Якщо надати довгий шлях до каталогу, він створить батьківські папки автоматично. Модуль - це супер набір npm-модуля fs, тому ви можете використовувати всі функції, fsякщо ви додасте цей модуль.
var dir = 'path/to/dir';
try {
fs.mkdirSync(dir);
} catch(e) {
if (e.code != 'EEXIST') throw e;
}
fs.exists()застаріло, але fs.existsSync()це не так. Чи можете ви додати посилання на ресурс, який говорить про fs.existsSync()амортизацію?
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");
}
Це може вам допомогти :)
ENOENT: такого файлу чи каталогу немає
Рішення
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 })
Я хотів би додати рефактор "Обіцяння набору тексту" відповіді josh3736 .
Це те ж саме і має однакові крайові випадки, просто трапляється використовувати Promises, typecript typedefs та працює з "строго використовувати".
// 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
}
});
});
}
З вузлом 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;
}
}
})();
Ви можете скористатися командою файлової системи ns.fs.stat, щоб перевірити, чи існує dir, і fs.mkdir для створення каталогу з зворотним викликом, або fs.mkdirSync для створення каталогу без зворотного виклику, наприклад, наприклад:
//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);
}
});
};
Ось невелика функція для рекурсивного створення каталогів:
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
}, '')
}
Використання асинхронізації / очікування:
const mkdirP = async (directory) => {
try {
return await fs.mkdirAsync(directory);
} catch (error) {
if (error.code != 'EEXIST') {
throw e;
}
}
};
Вам потрібно буде зазначити fs:
import nodeFs from 'fs';
import bluebird from 'bluebird';
const fs = bluebird.promisifyAll(nodeFs);