Đây có phải là cách đúng để tạo một thư mục nếu nó không tồn tại. Nó nên có sự cho phép đầy đủ cho kịch bản và những người khác có thể đọc được.
var dir = __dirname + '/upload';
if (!path.existsSync(dir)) {
fs.mkdirSync(dir, 0744);
}
Đây có phải là cách đúng để tạo một thư mục nếu nó không tồn tại. Nó nên có sự cho phép đầy đủ cho kịch bản và những người khác có thể đọc được.
var dir = __dirname + '/upload';
if (!path.existsSync(dir)) {
fs.mkdirSync(dir, 0744);
}
Câu trả lời:
var fs = require('fs');
var dir = './tmp';
if (!fs.existsSync(dir)){
fs.mkdirSync(dir);
}
Sync
các phương thức * thường là không có: không muốn chặn vòng lặp sự kiện
Không, vì nhiều lý do.
Các path
mô-đun không có một exists
/ existsSync
phương pháp. Nó nằm trong fs
mô-đun. (Có lẽ bạn vừa mắc lỗi đánh máy trong câu hỏi của bạn?)
Các tài liệu rõ ràng không khuyến khích bạn sử dụng exists
.
fs.exists()
là lỗi thời và chỉ tồn tại vì lý do lịch sử. Hầu như không bao giờ có một lý do để sử dụng nó trong mã của riêng bạn.Cụ thể, kiểm tra xem một tệp có tồn tại trước khi mở tệp đó là một mẫu chống khiến bạn dễ bị tổn thương trong điều kiện chủng tộc hay không: một quy trình khác có thể xóa tệp giữa các lệnh gọi đến
fs.exists()
vàfs.open()
. Chỉ cần mở tệp và xử lý lỗi khi nó không ở đó.
Vì chúng ta đang nói về một thư mục chứ không phải là một tập tin, lời khuyên này ngụ ý bạn chỉ nên gọi mkdir
và bỏ qua vô điều kiện EEXIST
.
Nói chung, bạn nên tránh *Sync
phương thức . Họ đang chặn, điều đó có nghĩa là hoàn toàn không có gì khác trong chương trình của bạn có thể xảy ra trong khi bạn vào đĩa. Đây là một hoạt động rất tốn kém và thời gian cần thiết để phá vỡ giả định cốt lõi của vòng lặp sự kiện của nút.
Các Sync
phương thức * thường ổn trong các tập lệnh nhanh đơn mục đích (các tập lệnh thực hiện một việc rồi thoát), nhưng hầu như không bao giờ được sử dụng khi bạn viết máy chủ: máy chủ của bạn sẽ không thể phản hồi cho bất kỳ ai trong toàn bộ thời gian của các yêu cầu I / O. Nếu nhiều yêu cầu của máy khách yêu cầu thao tác I / O, máy chủ của bạn sẽ nhanh chóng bị dừng lại.
Lần duy nhất tôi xem xét sử dụng Sync
các phương thức * trong ứng dụng máy chủ là trong một hoạt động xảy ra một lần (và chỉ một lần), khi khởi động. Ví dụ, require
thực sự sử dụngreadFileSync
để tải các mô-đun.
Ngay cả khi đó, bạn vẫn phải cẩn thận vì nhiều I / O đồng bộ có thể làm chậm thời gian khởi động máy chủ của bạn một cách không cần thiết.
Thay vào đó, bạn nên sử dụng các phương thức I / O không đồng bộ.
Vì vậy, nếu chúng ta kết hợp những lời khuyên đó, chúng ta sẽ nhận được một cái gì đó như thế này:
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
});
}
Và chúng ta có thể sử dụng nó như thế này:
ensureExists(__dirname + '/upload', 0744, function(err) {
if (err) // handle folder creation error
else // we're all good
});
Tất nhiên, điều này không giải thích cho các trường hợp cạnh như
0744 == 484
.
Tôi đã tìm thấy và mô-đun npm hoạt động như một cơ duyên cho việc này. Nó chỉ đơn giản là thực hiện một mkdir đệ quy khi cần, như "mkdir -p".
Các mkdir
phương pháp có khả năng đệ quy tạo bất kỳ thư mục trong một con đường mà không làm tồn tại, và bỏ qua những cái mà làm.
Từ các tài liệu Node 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;
});
LƯU Ý: Bạn sẽ cần nhập phần tích hợp fs
mô-đun tích hợp trước.
Bây giờ đây là một ví dụ mạnh mẽ hơn một chút, tận dụng các Mô-đun ES gốc (có bật cờ và mở rộng .mjs), xử lý các đường dẫn không gốc và chiếm các tên đường dẫn đầy đủ:
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');
}
});
}
Bạn có thể sử dụng nó như thế nào createDirectories('/components/widget/widget.js');
.
Và tất nhiên, có lẽ bạn sẽ muốn trở nên lạ mắt hơn bằng cách sử dụng các lời hứa với async / await để thúc đẩy việc tạo tệp theo cách nhìn đồng bộ dễ đọc hơn khi các thư mục được tạo; nhưng, điều đó vượt quá phạm vi câu hỏi.
Chỉ trong trường hợp bất kỳ ai quan tâm đến phiên bản một dòng. :)
//or in typescript: import * as fs from 'fs';
const fs = require('fs');
!fs.existsSync(dir) && fs.mkdirSync(dir);
Bạn chỉ có thể sử dụng mkdir
và bắt lỗi nếu thư mục tồn tại.
Đây là async (vì vậy thực hành tốt nhất) và an toàn.
fs.mkdir('/path', err => {
if (err && err.code != 'EEXIST') throw 'up'
.. safely do your stuff here
})
(Tùy chọn thêm đối số thứ hai với chế độ.)
Những suy nghĩ khác:
Bạn có thể sử dụng sau đó hoặc chờ đợi bằng cách sử dụng hứa hẹn bản địa .
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() })
Bạn có thể thực hiện phương thức hứa của riêng mình, đại loại như (chưa được kiểm tra):
let mkdirAsync = (path, mode) => new Promise(
(resolve, reject) => mkdir (path, mode,
err => (err && err.code !== 'EEXIST') ? reject(err) : resolve()
)
)
Để kiểm tra đồng bộ, bạn có thể sử dụng:
fs.existsSync(path) || fs.mkdirSync(path)
Hoặc bạn có thể sử dụng một thư viện, hai thứ phổ biến nhất
mkdir('/path').catch(err => { if (err.code != 'EEXIST') throw err;}).then(myFunc);
!==
thay vì!=
Với gói fs-Extra bạn có thể thực hiện việc này với một lớp lót :
const fs = require('fs-extra');
const dir = '/tmp/this/path/does/not/exist';
fs.ensureDirSync(dir);
Giải pháp tốt nhất sẽ là sử dụng mô-đun npm có tên là nút-fs-thêm . Nó có một phương thức gọi là mkdir
tạo thư mục mà bạn đề cập. Nếu bạn đưa ra một đường dẫn thư mục dài, nó sẽ tự động tạo các thư mục mẹ. Mô-đun này là một bộ siêu mô-đun npm fs
, vì vậy bạn cũng có thể sử dụng tất cả các chức năng fs
nếu bạn thêm mô-đun này.
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
var filessystem = require('fs');
var dir = './path/subpath/';
if (!filessystem.existsSync(dir)){
filessystem.mkdirSync(dir);
}else
{
console.log("Directory already exist");
}
Điều này có thể giúp bạn :)
ENOENT: không có tập tin hoặc thư mục như vậy
Giải pháp
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 })
Tôi muốn thêm một công cụ tái cấu trúc Promise của bản mô tả câu trả lời của josh3736 .
Nó thực hiện điều tương tự và có các trường hợp cạnh giống nhau, nó chỉ tình cờ sử dụng Promise, typedefs kiểu chữ và hoạt động với "sử dụng nghiêm ngặt".
// 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
}
});
});
}
Với nút 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;
}
}
})();
Bạn có thể sử dụng nút File System lệnh fs.stat để kiểm tra xem thư mục tồn tại và fs.mkdir để tạo ra một thư mục với gọi lại, hoặc fs.mkdirSync để tạo ra một thư mục mà không gọi lại, như ví dụ sau:
//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);
}
});
};
Đây là một chức năng nhỏ để tạo đệ quy các thư mục:
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
}, '')
}
Sử dụng async / await:
const mkdirP = async (directory) => {
try {
return await fs.mkdirAsync(directory);
} catch (error) {
if (error.code != 'EEXIST') {
throw e;
}
}
};
Bạn sẽ cần phải hứa fs
:
import nodeFs from 'fs';
import bluebird from 'bluebird';
const fs = bluebird.promisifyAll(nodeFs);