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