답변:
var fs = require('fs');
var dir = './tmp';
if (!fs.existsSync(dir)){
fs.mkdirSync(dir);
}
Sync메소드를 사용 하는 것은 일반적으로 아니오입니다 : 이벤트 루프를 차단하고 싶지 않습니다
아니요, 여러 가지 이유가 있습니다.
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
});
물론 이것은 다음과 같은 에지 사례를 설명하지 않습니다.
0744 == 484.
나는 이것에 대한 매력처럼 작동하는 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)또는 가장 인기있는 두 가지 라이브러리 인 라이브러리를 사용할 수 있습니다.
mkdir('/path').catch(err => { if (err.code != 'EEXIST') throw err;}).then(myFunc);
!==대신 사용하십시오!=
가장 좋은 해결책은 node-fs-extra 라는 npm 모듈을 사용하는 것 입니다. mkdir언급 한 디렉토리를 만드는 메소드가 있습니다. 긴 디렉토리 경로를 제공하면 상위 폴더가 자동으로 생성됩니다. 이 모듈은 수퍼 npm 모듈 세트이므로이 모듈 을 추가해도 fs모든 기능을 사용할 수 있습니다 fs.
var dir = 'path/to/dir';
try {
fs.mkdirSync(dir);
} catch(e) {
if (e.code != 'EEXIST') throw e;
}
Apr 2018: nodejs.org/api/fs.html#fs_fs_existssync_path
중요 : 그러한 파일이나 디렉토리가 없습니다.
해결책
const fs = require('fs') // in javascript
import * as fs from "fs" // in typescript
import fs from "fs" // in typescript
// it will create the directory if it does not exist.
!fs.existsSync(`./assets/`) && fs.mkdirSync(`./assets/`, { recursive: true })
josh3736 's answer의 Typescript Promise 리 팩터를 추가하고 싶습니다 .
그것은 똑같은 일을하고 가장자리가 똑같습니다. 약속을 사용하고 typescript typedef를 사용하고 "엄격한 사용"으로 작동합니다.
// 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
}
});
});
}
노드 10 + ES6 사용시 :
import path from 'path';
import fs from 'fs';
(async () => {
const dir = path.join(__dirname, 'upload');
try {
await fs.promises.mkdir(dir);
} catch (error) {
if (error.code === 'EEXIST') {
// Something already exists, but is it a file or directory?
const lstat = await fs.promises.lstat(dir);
if (!lstat.isDirectory()) {
throw error;
}
} else {
throw error;
}
}
})();
다음 예제와 같이 node File System 명령 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);
}
});
};
다음은 디렉토리를 반복적으로 작성하는 작은 기능입니다.
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
}, '')
}