Node.js는 폴더를 만들거나 기존 폴더를 사용합니다


186

Node.js의 문서를 이미 읽었으며 무언가를 놓치지 않으면 특정 작업, 특히 매개 변수에 포함 된 내용을 알려주지 않습니다 fs.mkdir(). 문서에서 볼 수 있듯이 그리 많지는 않습니다.

현재이 코드가 있는데 폴더를 만들거나 기존 폴더를 대신 사용하려고합니다.

fs.mkdir(path,function(e){
    if(!e || (e && e.code === 'EEXIST')){
        //do something with contents
    } else {
        //debug
        console.log(e);
    }
});

그러나 이것이 올바른 방법인지 궁금합니다. EEXIST폴더가 이미 존재하는지 알 수있는 올바른 방법으로 코드를 확인하고 있습니까? fs.stat()디렉토리를 만들기 전에 할 수 있다는 것을 알고 있지만 파일 시스템에는 이미 두 가지가 있습니다.

둘째, 오류 객체에 포함 된 내용, 매개 변수의 의미 등에 대한 세부 정보가 포함 된 Node.js에 대한 완전하거나 더 자세한 설명서가 있습니까?


31
작은 nitpick이지만를 제거하십시오 e &&. 경우 !e에 실패, 당신은 알고 etruthy입니다.
나는 게으른 증오

답변:


236

이를 수행하는 좋은 방법은 mkdirp 모듈 을 사용하는 입니다.

$ npm install mkdirp

디렉토리가 필요한 기능을 실행하는 데 사용하십시오. 경로가 생성 된 후 또는 경로가 이미 존재하면 콜백이 호출됩니다. errmkdirp가 디렉토리 경로를 작성하지 못한 경우 오류 가 설정됩니다.

var mkdirp = require('mkdirp');
mkdirp('/tmp/some/path/foo', function(err) { 

    // path exists unless there was an error

});

3
@Raugaral이을 사용하여 올바른 ( '무 의존적 추가됨'으로 읽음) 대답은 낮은 것 같습니다 fs.exists(Sync).
Ricardo Pedroni 2019 년

@meawoppl, 그것은 'makedirectory'p입니다. 'p'는 알려져 있지 않다.
앤드류

4
@RicardoPedroni 올바른 방법은 모듈을 사용하는 것입니다. 모듈은 일반적으로 하나의 문제를 해결하기 위해 전적으로 노력하며 종종 유지 관리됩니다. npm으로 쉽게 업데이트 할 수 있습니다. 또한 fs.exists [동기화]를 사용하면 경쟁 조건을 암시하므로 사용하지 마십시오.
1j01

16
@ 1j01 플랫폼이 기본적으로 작업을 지원하는 경우 올바른 방법이 모듈을 사용하는 것이라고 생각하지 않습니다. 혼돈의 길입니다. 기술적 인 관점에서 더 나은 답변이 있다는 데 동의해야합니다.
c ..

2
@ 1j01 또한 동기화 작업을 사용하면 경쟁 조건이 해결되므로 경쟁 조건을 의미합니다.
c ..

193

편집하다: 이 답변은 매우 인기가 있기 때문에 최신 사례를 반영하도록 업데이트했습니다.

노드> = 10

{ recursive: true }노드의 새로운 옵션fs 이제 이것을 기본적으로 허용합니다. 이 옵션은 UNIX의 동작을 모방합니다.mkdir -p . 재귀 적으로 경로의 모든 부분이 존재하는지 확인하고 어떤 경우에도 오류가 발생하지 않습니다.

(참고 : 여전히 EPERM또는EACCESS 때문에 더 나은 여전히하는에 포장try {} catch (e) {} 구현이에 취약합니다.)

동기식 버전.

fs.mkdirSync(dirpath, { recursive: true })

비동기 버전

await fs.promises.mkdir(dirpath, { recursive: true })

이전 노드 버전

사용하여 try {} catch (err) {} 경쟁 조건을 겪지 않고 매우 우아하게 달성 할 수 있습니다.

존재 여부 확인과 디렉토리 작성 사이의 데드 타임을 방지하기 위해 디렉토리를 바로 작성하고 오류가있는 경우 무시합니다. EEXIST (디렉토리가 이미 존재하는 경우) .

오류가없는 경우 EEXIST, 그러나, 우리는 우리가 같은 취급 될 수 있기 때문에, 오류가 발생한다고 EPERMEACCES

function ensureDirSync (dirpath) {
  try {
    return fs.mkdirSync(dirpath)
  } catch (err) {
    if (err.code !== 'EEXIST') throw err
  }
}

들어 mkdir -p-like 재귀 행동, 예를 들어 ./a/b/c, 당신은 dirpath의 모든 부분에 전화를해야 할 것, 예를 들면 ./a, ./a/b,.a/b/c


var fs = Npm.require ( 'fs'); var dir = process.env.PWD + '/ files / users /'+ this.userId + '/'; 시도 {fs.mkdirSync (dir); } catch (e) {if (e.code! = 'EEXIST') throw e; }
Aaron

코드를 작성하고 다음과 같이 카탈로그 작성을 사용하는 js 스크립트를 작성하십시오. mkdirpSync (path.join (__ dirname, 'first', 'second', 'third', 'ololol', 'works')); 그러나이 오류가 발생했습니다 : $ node 1.js fs.js : 747 return binding.mkdir (pathModule._makeLong (path), ^ 오류 : EPERM, Object.fs의 오류 (네이티브)에서 'C : \'작업이 허용되지 않습니다. Object. <anonymous> (C : \ Users \ MAXIM \ Desktop \ test \)의 mkdirpSync (C : \ Users \ MAXIM \ Desktop \ test \ 1.js : 15 : 8)에서 mkdirSync (fs.js : 747 : 18) 1.js : 19 : 1) ... 당신은 잘못 될 수있는 것을 제안 할 수 분명히 창에 사용 :?
Alendorff

EPERM은 권한 문제처럼 보이므로 스크립트가 실행을 중단했을 것입니다.
Christophe Marois

나는 그것이 더 나을 것이라고 생각한다 : var mkdirpSync = function (dirpath) {var parts = dirpath.split (path.sep); for (var i = 1; i <= parts.length; i ++) {try {fs.mkdirSync (path.join.apply (null, parts.slice (0, i))); } catch (오류) {if (error.code! = 'EEXIST') {throw error; }}}}
Manish

1
경고 : 경로가 /
acemtp

62

빠르고 더러운 하나의 라이너를 원한다면 다음을 사용하십시오.

fs.existsSync("directory") || fs.mkdirSync("directory");

1
fs.exists더 이상 사용되지 않습니다 : nodejs.org/api/fs.html#fs_fs_exists_path_callback
adius

7
fs.existsSync (...)는 더 이상 사용되지 않으므로이 답변은 괜찮습니다.
Dan Haywood

헤즈 업! 작동하지 않습니다 "DIR / foo는 / 바"즉,가에서 mkdir -p 플래그 기능 부족
칼 Pokus

경쟁 조건도 있습니다
Evert

26

에 대한 node.js 문서 fs.mkdir 기본적으로에 대한 Linux 매뉴얼 페이지를 참조하십시오 mkdir(2). 그것은EEXIST 경로가 존재하지만이 경로를 이동하는 경우 어색한 코너 케이스를 생성하는 디렉토리가 아닌 경우에도 표시됩니다.

전화하는 것이 더 나을 수도 있습니다 fs.stat경로가 존재하는지 여부와 단일 호출의 디렉토리인지 알려주는 이 . 디렉토리가 이미 존재하는 일반적인 경우 (단일 가정)의 경우 단일 파일 시스템 적중입니다.

fs모듈 메소드는 네이티브 C API를 둘러싼 씬 래퍼이므로 자세한 내용은 node.js 문서에서 참조 된 매뉴얼 페이지를 확인해야합니다.


19
stat전에 전화 mkdir하면 경쟁 조건이 생길 수 있습니다.이를 염두에 두십시오.
Roger Lipscombe

24

이것을 사용할 수 있습니다 :

if(!fs.existsSync("directory")){
    fs.mkdirSync("directory", 0766, function(err){
        if(err){
            console.log(err);
            // echo the result back
            response.send("ERROR! Can't make the directory! \n");
        }
    });
}

1
-1. 나는 이것이 작동한다고 생각하지 않으며 statSync, 엔티티가 전혀 존재하지 않으면 오류가 발생하여 코드가 충돌합니다. 이것을 try/catch블록 으로 싸야합니다 .
Chris Foster

2
미안해, 내가 틀렸어. "existsSync"에 대한 "statSync"변경
Raugaral

5
nodejs.org/api/fs.html#fs_fs_mkdirsync_path_mode 에 따르면 mkdir의 동기화 변형은 콜백을 허용하지 않습니다
danwellman

1
에 따르면 nodejs.org/api/fs.html#fs_fs_existssync_path , fs.existsSync()그리고 fs.exists()더 이상 사용되지 않습니다.
pau.moreno

7

모듈이없는 솔루션을 제안합니다 (누적 모듈은 특히 몇 줄로 작성할 수있는 작은 기능의 유지 관리를 위해 권장되지 않습니다 ...) :

마지막 업데이트 :

v10.12.0에서 NodeJS 구현 재귀 옵션 :

// Create recursive folder
fs.mkdir('my/new/folder/create', { recursive: true }, (err) => { if (err) throw err; });

업데이트 :

// Get modules node
const fs   = require('fs');
const path = require('path');

// Create 
function mkdirpath(dirPath)
{
    if(!fs.accessSync(dirPath, fs.constants.R_OK | fs.constants.W_OK))
    {
        try
        {
            fs.mkdirSync(dirPath);
        }
        catch(e)
        {
            mkdirpath(path.dirname(dirPath));
            mkdirpath(dirPath);
        }
    }
}

// Create folder path
mkdirpath('my/new/folder/create');

fs.exists()노드 v9에서는 더 이상 사용되지 않습니다. 사용하는 fs.access()대신. ( undefined파일이 존재하면 반환 ; 그렇지 않으면 오류가 발생 ENOENT)
chharvey

npm 패키지가 없으면 작동합니다. 귀중한 코드입니다. 감사합니다
Karthik Sridharan

이것은 기존의 긴 경로 아래에 폴더를 만드는 데 훨씬 좋습니다.) 감사합니다.
Tsung Goh

1
무엇에 대해 fs.mkdirSync('my/new/folder/create', {recursive: true})?
saitho

감사 ! 다른 사람들을 돕기 위해 게시물을 업데이트합니다. 노드 10.12.0이 너무 최근입니다.
Liberateur


4

디렉토리를 만들 때 사용하는 ES6 코드는 다음과 같습니다 (없는 경우).

const fs = require('fs');
const path = require('path');

function createDirectory(directoryPath) {
  const directory = path.normalize(directoryPath);

  return new Promise((resolve, reject) => {
    fs.stat(directory, (error) => {
      if (error) {
        if (error.code === 'ENOENT') {
          fs.mkdir(directory, (error) => {
            if (error) {
              reject(error);
            } else {
              resolve(directory);
            }
          });
        } else {
          reject(error);
        }
      } else {
        resolve(directory);
      }
    });
  });
}

const directoryPath = `${__dirname}/test`;

createDirectory(directoryPath).then((path) => {
  console.log(`Successfully created directory: '${path}'`);
}).catch((error) => {
  console.log(`Problem creating directory: ${error.message}`)
});

노트 :

  • 의 초기에는 createDirectory기능, I (예 :이 켜집니다 운영 체제의 경로 구분자 유형이 지속적으로 사용됩니다 보장의 경로를 정상화 C:\directory/testC:\directory\test (윈도우에있는 경우)
  • fs.exists되어 사용되지 않는 내가 사용하는 이유, 그건 fs.stat디렉토리가 이미 존재하는지 확인
  • 디렉토리가 존재하지 않는 경우, 에러 코드가 될 것입니다 ENOENT( E rror NO ENT 공예)
  • 디렉토리 자체는 다음을 사용하여 생성됩니다. fs.mkdir
  • 나는 fs.mkdir상대를 차단 하는 것보다 비동기 함수 를 선호하며 fs.mkdirSync줄 바꿈 때문에 Promise디렉토리가 성공적으로 생성 된 후에 만 ​​디렉토리 경로가 반환되도록 보장합니다

불필요한 모듈이 필요없는 깨끗한 솔루션에 감사합니다. 그것은 나를 위해 완벽하게 작동했습니다. 나는 이런 식으로 더 많은 답변이 있기를 바랍니다!
Ken Lyon

3

내 의견으로는 자바 스크립트로 코딩하는 동안 파일 시스템 적중을 계산하지 않는 것이 좋습니다. 그러나 (1) stat& mkdir및 (2) mkdir오류 코드를 확인 (또는 삭제)하면 두 가지 방법 모두 원하는 작업을 수행하는 올바른 방법입니다.


-1, 나는 확인하거나 버리는 것이 어떻게 올바른 방법인지 알 수 없습니다. 이것은 거의 대답이 아닙니다.
Matt Ball

디렉토리를 mkdir하거나 기존 디렉토리를 사용하는 좋은 방법입니다. 왜 보지 못하는지 모르겠습니다. 오류 코드를 확인하는 것은 정중 한 것이며 오류 코드를 삭제하는 것은 좋은 것입니다. 동의하지 않습니까?
양철웅

1
어쩌면 이것이 언어 장벽 문제 일 수도 있지만 OP가 묻는 질문에 대답하지 않는 것으로 읽었습니다.
Matt Ball

나는 당신의 요점이 무엇인지 봅니다. 그러나 올바른 일을하는 방법은 여러 가지가 있다고 생각합니다. 감사.
양철웅

2

각 사용자에 대한 동적 이름 디렉토리를 작성하십시오 ...이 코드를 사용하십시오

***suppose email contain user mail address***

var filessystem = require('fs');
var dir = './public/uploads/'+email;

if (!filessystem.existsSync(dir)){
  filessystem.mkdirSync(dir);

}else
{
    console.log("Directory already exist");
}

1

파일 시스템 모듈을 사용하여이 모든 작업을 수행 할 수 있습니다.

const
  fs = require('fs'),
  dirPath = `path/to/dir`

// Check if directory exists.
fs.access(dirPath, fs.constants.F_OK, (err)=>{
  if (err){
    // Create directory if directory does not exist.
    fs.mkdir(dirPath, {recursive:true}, (err)=>{
      if (err) console.log(`Error creating directory: ${err}`)
      else console.log('Directory created successfully.')
    })
  }
  // Directory now exists.
})

디렉토리가 존재하는지 확인할 필요조차 없습니다. 다음 코드는 또한 디렉토리가 이미 존재하거나 작성되었음을 보증합니다.

const
  fs = require('fs'),
  dirPath = `path/to/dir`

// Create directory if directory does not exist.
fs.mkdir(dirPath, {recursive:true}, (err)=>{
  if (err) console.log(`Error creating directory: ${err}`)
  // Directory now exists.
})

0

Raugaral의 답변 이지만 -p 기능이 있습니다. 추악하지만 작동합니다.

function mkdirp(dir) {
    let dirs = dir.split(/\\/).filter(asdf => !asdf.match(/^\s*$/))
    let fullpath = ''

    // Production directory will begin \\, test is on my local drive.
    if (dirs[0].match(/C:/i)) {
        fullpath = dirs[0] + '\\'
    }
    else {
        fullpath = '\\\\' + dirs[0] + '\\'
    }

    // Start from root directory + 1, build out one level at a time.
    dirs.slice(1).map(asdf => {
        fullpath += asdf + '\\'
        if (!fs.existsSync(fullpath)) {
            fs.mkdirSync(fullpath)
        }
    })
}//mkdirp

0

매우 간단하고 쉽게 읽을 수있는 Teemu Ikonen의 답변에 대한 새로운 대안 ensureDirfs-extra패키지 방법 을 사용하는 것입니다 .

내장 된 fs모듈을 대체 할 수있을 뿐만 아니라 fs패키지 기능 외에 다른 기능도 많이 있습니다.

ensureDir이름에서 알 수 있듯이 방법은, 디렉토리가 존재하는지 확인합니다. 디렉토리 구조가 없으면 작성됩니다. 처럼 mkdir -p. 끝 폴더뿐만 아니라 이미 존재하지 않는 경우 전체 경로가 만들어집니다.

위에 제공된 것은 async그것 의 버전입니다. 또한 메소드 형식으로이를 수행하는 동기 메소드도 있습니다 ensureDirSync.


0

의 @Liberateur 의 답변 이 저에게 효과적이지 않았습니다 (노드 v8.10.0). 약간의 수정만으로 트릭을 수행했지만 이것이 올바른 방법인지 확실하지 않습니다. 제안 해주세요.

// Get modules node
const fs   = require('fs');
const path = require('path');

// Create
function mkdirpath(dirPath)
{
    try {
        fs.accessSync(dirPath, fs.constants.R_OK | fs.constants.W_OK);
    }
    catch(err) {
        try
        {
            fs.mkdirSync(dirPath);
        }
        catch(e)
        {
            mkdirpath(path.dirname(dirPath));
            mkdirpath(dirPath);
        }
    }
}

// Create folder path
mkdirpath('my/new/folder/create');
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.