Правильно ли это создать каталог, если он не существует. Он должен иметь полное разрешение для script и читать другие.
var dir = __dirname + '/upload';
if (!path.existsSync(dir)) {
fs.mkdirSync(dir, 0744);
}
Правильно ли это создать каталог, если он не существует. Он должен иметь полное разрешение для script и читать другие.
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);
}
Нет, по нескольким причинам.
Модуль path
не имеет метода exists
/existsSync
. Он находится в модуле fs
. (Возможно, вы просто сделали опечатку в своем вопросе?)
Документы явно препятствуют вам использовать exists
.
fs.exists()
является анахронизмом и существует только по историческим причинам. В его собственном коде не должно быть причин использовать его.В частности, проверка наличия файла перед его открытием - это анти-шаблон, который оставляет вас уязвимыми для условий гонки: другой процесс может удалить файл между вызовами
fs.exists()
иfs.open()
. Просто откройте файл и обработайте ошибку, если она там отсутствует.
Поскольку мы говорим о каталоге, а не о файле, этот совет подразумевает, что вы должны просто безоговорочно вызвать mkdir
и игнорировать EEXIST
.
В общем, вам следует избегать методов * Sync
. Они блокируют, что означает, что абсолютно ничего не происходит в вашей программе, когда вы идете на диск. Это очень дорогостоящая операция, и время, затрачиваемое на это, прерывает основное предположение цикла событий node.
Методы * 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
});
Конечно, это не учитывает краевые случаи, такие как
Я нашел и модуль npm, который работает как шарм для этого. Он просто рекурсивно mkdir при необходимости, например, "mkdir -p".
На всякий случай кто-то интересуется одной строкой. :)
//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
})
(При необходимости добавьте второй аргумент в режим.)
Другие мысли:
Вы можете использовать его или ждать, используя native promisify.
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() })
Вы можете сделать свой собственный метод обещания, что-то вроде (untested):
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)
Или вы можете использовать библиотеку, две самые популярные
Лучшим решением было бы использовать модуль npm, называемый node-fs-extra. У него есть метод под названием mkdir
, который создает указанный вами каталог. Если вы укажете длинный путь к каталогу, он автоматически создаст родительские папки. Модуль представляет собой супер-набор модуля npm fs
, поэтому вы можете использовать все функции в 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;
});
ПРИМЕЧАНИЕ. Сначала вам нужно будет импортировать встроенный модуль fs
.
Теперь вот немного более надежный пример, который использует собственные модули ES (с включенным флагом и расширением .mjs), обрабатывает пути без полномочий root и учитывает полные пути:
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/await, чтобы использовать создание файлов в более читабельном синхронном виде при создании каталогов; но это выходит за рамки вопроса.
var dir = 'path/to/dir';
try {
fs.mkdirSync(dir);
} catch(e) {
if (e.code ~= 'EEXIST') throw e;
}
С пакетом fs-extra вы можете сделать это с помощью одной строки:
const fs = require('fs-extra');
const dir = '/tmp/this/path/does/not/exist';
fs.ensureDirSync(dir);
var filessystem = require('fs');
var dir = './path/subpath/';
if (!filessystem.existsSync(dir)){
filessystem.mkdirSync(dir);
}else
{
console.log("Directory already exist");
}
Это может вам помочь:)
Я хочу добавить Typescript репликатор Promise josh3736 answer.
Он делает то же самое и имеет одни и те же граничные случаи, просто используется Promises, Typescript typedefs и работает с "use strict".
// 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
}
});
});
}
Вот небольшая функция для рекурсивного создания каталогов:
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
}, '')
}
Использование async/wait:
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);
ENOENT: нет такого файла или каталога, mkdir './assets/
Решение
// const fs = require('fs') in javascript
// import * as fs from "fs" in typescript
// import fs from "fs" in typescript
!fs.existsSync('./assets/') && fs.mkdirSync('./assets/', { recursive: true })
Вы можете использовать команду файловой системы узла 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);
}
});
};