Подтвердить что ты не робот

Node как создать каталог, если он не существует?

Правильно ли это создать каталог, если он не существует. Он должен иметь полное разрешение для script и читать другие.

var dir = __dirname + '/upload';
if (!path.existsSync(dir)) {
    fs.mkdirSync(dir, 0744);
}
4b9b3361

Ответ 1

var fs = require('fs');
var dir = './tmp';

if (!fs.existsSync(dir)){
    fs.mkdirSync(dir);
}

Ответ 2

Нет, по нескольким причинам.

  • Модуль 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
});

Конечно, это не учитывает краевые случаи, такие как

  • Что произойдет, если папка будет удалена во время работы вашей программы? (предполагая, что вы только проверяете, что он существует один раз во время запуска)
  • Что произойдет, если папка уже существует, но с неправильными разрешениями?

Ответ 3

Я нашел и модуль npm, который работает как шарм для этого. Он просто рекурсивно mkdir при необходимости, например, "mkdir -p".

https://www.npmjs.com/package/mkdirp

Ответ 4

На всякий случай кто-то интересуется одной строкой. :)

//or in typescript: import * as fs from 'fs';
const fs = require('fs');
!fs.existsSync(dir) && fs.mkdirSync(dir);

Ответ 5

Вы можете просто использовать mkdir и поймать ошибку, если папка существует.
Это асинхронный (так рекомендуется) и безопасный.

fs.mkdir('/path', err => { 
    if (err && err.code != 'EEXIST') throw 'up'
    .. safely do your stuff here  
    })

(При необходимости добавьте второй аргумент в режим.)


Другие мысли:

  1. Вы можете использовать его или ждать, используя 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() })
    
  2. Вы можете сделать свой собственный метод обещания, что-то вроде (untested):

    let mkdirAsync = (path, mode) => new Promise(
       (resolve, reject) => mkdir (path, mode, 
          err => (err && err.code !== 'EEXIST') ? reject(err) : resolve()
          )
       )
    
  3. Для синхронной проверки вы можете использовать:

    fs.existsSync(path) || fs.mkdirSync(path)
    
  4. Или вы можете использовать библиотеку, две самые популярные

    • mkdirp (просто папки)
    • fsextra (supersets fs, добавляет много полезного материала)

Ответ 6

Лучшим решением было бы использовать модуль npm, называемый node-fs-extra. У него есть метод под названием mkdir, который создает указанный вами каталог. Если вы укажете длинный путь к каталогу, он автоматически создаст родительские папки. Модуль представляет собой супер-набор модуля npm fs, поэтому вы можете использовать все функции в fs также, если вы добавите этот модуль.

Ответ 7

Метод mkdir имеет возможность рекурсивно создавать любые каталоги на пути, которые не существуют, и игнорировать те, которые существуют.

С Node v10/11 документов:

// 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, чтобы использовать создание файлов в более читабельном синхронном виде при создании каталогов; но это выходит за рамки вопроса.

Ответ 8

var dir = 'path/to/dir';
try {
  fs.mkdirSync(dir);
} catch(e) {
  if (e.code ~= 'EEXIST') throw e;
}

Ответ 10

    var filessystem = require('fs');
    var dir = './path/subpath/';

    if (!filessystem.existsSync(dir)){
        filessystem.mkdirSync(dir);
    }else
    {
        console.log("Directory already exist");
    }

Это может вам помочь:)

Ответ 11

Я хочу добавить 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
                }
            });
    });
}

Ответ 12

Вот небольшая функция для рекурсивного создания каталогов:

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
  }, '')
}

Ответ 13

Использование 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);

Ответ 14

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 })

Ответ 15

Вы можете использовать команду файловой системы узла 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);
        }
    });
};