Node.js에서 파일에 쓸 때 디렉토리 만들기


134

Node.js를 다루면서 약간의 문제가 발견되었습니다. 라는 디렉토리에있는 스크립트가 있습니다 data. 스크립트가 서브 디렉토리 내의 서브 디렉토리에있는 파일에 일부 데이터를 쓰려고합니다 data. 그러나 다음과 같은 오류가 발생합니다.

{ [Error: ENOENT, open 'D:\data\tmp\test.txt'] errno: 34, code: 'ENOENT', path: 'D:\\data\\tmp\\test.txt' }

코드는 다음과 같습니다.

var fs = require('fs');
fs.writeFile("tmp/test.txt", "Hey there!", function(err) {
    if(err) {
        console.log(err);
    } else {
        console.log("The file was saved!");
    }
}); 

Node.js가 파일에 쓰기 위해 종료되지 않으면 디렉토리 구조를 만드는 방법을 찾는 데 도움이 될 수 있습니까?


1
fs.promises.mkdir(path.dirname("tmp/test.txt"), {recursive: true}).then(x => fs.promises.writeFile("tmp/test.txt", "Hey there!"))
Offenso

답변:


127

노드> 10.12.0

fs.mkdir은 이제 { recursive: true }다음과 같은 옵션을 허용합니다 .

// 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.promises.mkdir('/tmp/a/apple', { recursive: true }).catch(console.error);

노드 <= 10.11.0

mkdirp 또는 fs-extra 같은 패키지를 사용 하여이 문제를 해결할 수 있습니다 . 패키지를 설치하지 않으려면 아래 Tiago Peres França의 답변을 참조하십시오.


4
그게 내가 가고있는 것입니다 ...이 통계가 나를 이겼습니다.
Aran Mulholland 2014 년

참고 fs.promises아직 실험 nodejs.org/dist/latest-v10.x/docs/api/...
lasec0203

132

추가 패키지를 사용하지 않으려면 파일을 만들기 전에 다음 함수를 호출하면됩니다.

var path = require('path'),
    fs = require('fs');

function ensureDirectoryExistence(filePath) {
  var dirname = path.dirname(filePath);
  if (fs.existsSync(dirname)) {
    return true;
  }
  ensureDirectoryExistence(dirname);
  fs.mkdirSync(dirname);
}

2
이것은 stackoverflow.com/questions/4482686/…을 기반으로 하여 statSync대신에 사용해야 합니다.existsSync
GavinR

1
path마찬가지로해야 할 필요가있는 패키지도 fs: var path = require('path')경우에 사람이 궁금됩니다. 노드 문서를 참조하십시오 .
Rafael Emshoff

9
fs.existsSync되어 있지 되지fs.exists입니다.
zzzzBov

6
fs.existsSync 함수가 더 이상 사용되지 않는지에 대해 약간의 혼동이있었습니다. 처음에는 이해를 통해 그 내용을 알았으므로이를 반영하여 답변을 업데이트했습니다. 그러나 이제 @zzzzBov가 지적한 것처럼 설명서에는 fs.exists 만 더 이상 사용되지 않으며 fs.existsSync의 사용은 여전히 ​​유효하다고 명시되어 있습니다. 이러한 이유로 이전 코드를 삭제했으며 이제 답변에는 더 간단한 솔루션 (fs.existsSync 사용) 만 포함되어 있습니다.
Tiago Peres França

1
@chrismarx는 "/home/documents/a/b/c/myfile.txt"경로를 상상해보십시오. "/ home / documents"는 존재하지만 그 앞에있는 모든 것은 존재하지 않습니다. "ensureDirectoryExistence"가 처음으로 호출 될 때 dirname은 "/ home / documents / a / b / c"입니다. "/ home / documents / a / b"도 존재하지 않기 때문에 지금 fs.mkdirSync (dirname)을 호출 할 수 없습니다. "c"디렉토리를 만들려면 먼저 "/ home / documents / a / b"가 있는지 확인해야합니다.
Tiago Peres França

43

노드-FS-추가 하면 쉽게 할 수있다.

설치

npm install --save fs-extra

그런 다음 outputFile방법을 사용하십시오 . 그것의 문서는 말합니다 :

부모 디렉토리가 존재하지 않는 경우 디렉토리가 생성된다는 점을 제외하면 writeFile과 거의 동일합니다 (즉, 덮어 씁니다).

세 가지 방법으로 사용할 수 있습니다.

콜백 스타일

const fse = require('fs-extra');

fse.outputFile('tmp/test.txt', 'Hey there!', err => {
  if(err) {
    console.log(err);
  } else {
    console.log('The file was saved!');
  }
})

약속 사용

promises 을 사용 하고 희망이 있다면 이것이 코드입니다.

fse.outputFile('tmp/test.txt', 'Hey there!')
   .then(() => {
       console.log('The file was saved!');
   })
   .catch(err => {
       console.error(err)
   });

동기화 버전

동기화 버전을 원하면 다음 코드를 사용하십시오.

fse.outputFileSync('tmp/test.txt', 'Hey there!')

자세한 내용은 outputFile설명서 및 모든 node-fs-extra 지원 방법을 확인하십시오 .


26

뻔뻔한 플러그 경고!

원하는 경로 구조에서 각 디렉토리를 확인하고 존재하지 않는 경우 수동으로 만들어야합니다. 그렇게하는 모든 도구는 이미 Node의 fs 모듈에 있지만 내 mkpath 모듈로 간단하게 모든 작업을 수행 할 수 있습니다 : https://github.com/jrajav/mkpath


1
파일을 직접 작성하거나 디렉토리 구조 만 작성합니까? 파일을 만들 때 디렉토리 구조와 함께 파일을 만드는 솔루션을 찾고 있습니다.
Hirvesh

디렉토리 구조 만 mkdir / path를 먼저 수행하고 오류가 없으면 파일 작성을 진행하십시오. 쓸 파일의 전체 경로가 주어지면 동시에 두 가지를 동시에 수행하는 함수를 작성하는 것만 큼 간단합니다. path.basename을
jrajav

1
실제로, 나는 2 분 안에 그것을 썼을 정도로 간단했다 . :) (테스트되지 않음)
jrajav

업데이트 : 테스트하고 편집했습니다. 처음 작동하지 않으면 다시 시도하십시오.
jrajav

8
@Kiyura 이것은 널리 사용되는 mkdirp와 어떻게 다릅니 까?
David Weldon

9

아직 댓글을 달 수 없으므로 @ tiago-peres-frança 환상적인 솔루션 (감사합니다!)을 기반으로 향상된 답변을 게시하고 있습니다. 경로에 마지막 디렉토리 만 누락 된 경우 그의 코드는 디렉토리를 만들지 않습니다. 예를 들어 입력은 "C : / test / abc"이고 "C : / test"는 이미 존재합니다. 작동하는 스 니펫은 다음과 같습니다.

function mkdirp(filepath) {
    var dirname = path.dirname(filepath);

    if (!fs.existsSync(dirname)) {
        mkdirp(dirname);
    }

    fs.mkdirSync(filepath);
}

1
@tiago의 솔루션에 파일 경로 가 필요하기 때문 입니다. 귀하의 경우 abc에는 디렉토리를 작성 해야하는 파일로 해석됩니다. abc디렉토리를 만들려면 경로에 더미 파일을 추가하십시오 (예 :) C:/test/abc/dummy.txt.
Sphinxxx

재귀 사용 :fs.promises.mkdir(path.dirname(file), {recursive: true}).then(x => fs.promises.writeFile(file, data))
Offenso

1
@ Offenso는 최상의 솔루션이지만 Node.js 버전 10.12 이상에만 해당됩니다.
Nickensoul

8

내 충고는 : 몇 줄의 코드로 쉽게 할 수있을 때 종속성에 의존하지 않도록 노력하십시오 .

14 줄의 코드 로 달성하려는 내용은 다음과 같습니다 .

fs.isDir = function(dpath) {
    try {
        return fs.lstatSync(dpath).isDirectory();
    } catch(e) {
        return false;
    }
};
fs.mkdirp = function(dirname) {
    dirname = path.normalize(dirname).split(path.sep);
    dirname.forEach((sdir,index)=>{
        var pathInQuestion = dirname.slice(0,index+1).join(path.sep);
        if((!fs.isDir(pathInQuestion)) && pathInQuestion) fs.mkdirSync(pathInQuestion);
    });
};

1
세 번째 줄이 이렇게 좋을까요? return fs.lstatSync(dpath).isDirectory()그렇지 않으면 isDirectory ()가 false를 반환하면 어떻게됩니까?
조르지오 아레 수

2
재귀 사용 :fs.promises.mkdir(path.dirname(file), {recursive: true}).then(x => fs.promises.writeFile(file, data))
Offenso

1
@Offenso 그것은 노드 8에 의해 지원되지 않습니다
Ievgen Naida

2

이 기능이 필요했기 때문에이 모듈을 방금 게시했습니다.

https://www.npmjs.org/package/filendir

Node.js fs 메소드 주위의 래퍼처럼 작동합니다. 당신은 그것을 정확하게 같은 방법을 사용할 수 있도록 때와 fs.writeFilefs.writeFileSync(비동기 및 동기 쓰기 모두)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.