디렉토리가없는 경우이를 작성하는 올바른 방법입니까? 스크립트에 대한 모든 권한이 있어야하며 다른 사람이 읽을 수 있어야합니다.
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
메소드 는 피해야합니다 . 차단 중이므로 디스크로 이동하는 동안 프로그램에서 다른 어떤 것도 발생할 수 없습니다. 이것은 매우 비용이 많이 드는 작업이며 시간이 걸리므로 노드의 이벤트 루프에 대한 핵심 가정이 깨집니다.*
Sync
방법은 보통 단일 목적의 빠른 스크립트 (한 가지 작업을 수행 한 다음 종료하는 스크립트)에서 적합하지만 서버를 작성할 때는 거의 사용하지 않아야합니다. 서버는 전체 기간 동안 누군가에게 응답 할 수 없습니다. I / O 요청 중 여러 클라이언트 요청에 I / O 작업이 필요한 경우 서버가 매우 빨리 중단됩니다.
Sync
서버 응용 프로그램에서 * 메서드를 사용하는 유일한 방법 은 시작할 때 한 번만 수행되는 작업입니다 . 예를 들어require
실제로readFileSync
모듈을로드 데 사용합니다.그럼에도 불구하고 많은 동기 I / O가 불필요하게 서버의 시작 시간을 느리게 할 수 있기 때문에 여전히주의해야합니다.
대신 비동기 I / O 방법을 사용해야합니다.
그래서 우리가 그 조언들을 정리하면, 우리는 다음과 같은 것을 얻습니다 :
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 -p”와 같이 필요할 때 재귀 적으로 mkdir을 수행합니다.
답변
이 mkdir
방법에는 재귀 적으로 생성 하는 기능이 있습니다 존재하지 않는 경로에 디렉토리 하고 존재하지 않는 디렉토리를 무시할 수 있습니다.
로부터 노드 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 확장명 사용)을 활용하고 루트가 아닌 경로를 처리하며 전체 경로 이름을 설명하는 좀 더 강력한 예입니다.
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와 함께 promise를 사용하여 디렉토리를 만들 때 더 읽기 쉬운 동기식 방식으로 파일 작성을 활용함으로써 더 멋진 모습을 원할 것입니다. 그러나 그것은 질문의 범위를 벗어납니다.
답변
한 줄 버전에 관심이있는 사람을 위해. 🙂
//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() })
-
당신은 (unested)와 같은 자신의 약속 방법을 만들 수 있습니다 :
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)
-
또는 가장 인기있는 두 가지 라이브러리 인 라이브러리를 사용할 수 있습니다.