Làm cách nào tôi có thể kiểm tra đồng bộ, bằng cách sử dụng node.js , nếu tệp hoặc thư mục tồn tại?
exists
chỉ thêm các cuộc gọi lại không cần thiết.
Làm cách nào tôi có thể kiểm tra đồng bộ, bằng cách sử dụng node.js , nếu tệp hoặc thư mục tồn tại?
exists
chỉ thêm các cuộc gọi lại không cần thiết.
Câu trả lời:
Câu trả lời cho câu hỏi này đã thay đổi qua nhiều năm. Các hiện câu trả lời là ở đây ở phía trên, sau đó là câu trả lời khác nhau trong những năm qua trong thứ tự thời gian:
Bạn có thể sử dụng fs.existsSync()
:
const fs = require("fs"); // Or `import fs from "fs";` with ESM
if (fs.existsSync(path)) {
// Do something
}
Nó đã bị phản đối trong vài năm, nhưng không còn nữa. Từ các tài liệu:
Lưu ý rằng
fs.exists()
không được chấp nhận, nhưngfs.existsSync()
không. (Tham số gọi lại đểfs.exists()
chấp nhận các tham số không phù hợp với các cuộc gọi lại Node.js khác.fs.existsSync()
Không sử dụng gọi lại.)
Bạn đã đặc biệt yêu cầu kiểm tra đồng bộ , nhưng nếu bạn có thể sử dụng kiểm tra không đồng bộ thay thế (thường là tốt nhất với I / O), hãy sử dụng fs.promises.access
nếu bạn đang sử dụng các async
chức năng hoặc fs.access
(vì exists
không được dùng nữa ) nếu không:
Trong một async
chức năng:
try {
await fs.promises.access("somefile");
// The check succeeded
} catch (error) {
// The check failed
}
Hoặc với một cuộc gọi lại:
fs.access("somefile", error => {
if (!error) {
// The check succeeded
} else {
// The check failed
}
});
Dưới đây là các câu trả lời lịch sử theo thứ tự thời gian:
stat
/ statSync
hoặc lstat
/ lstatSync
)exists
/ existsSync
)exists
/ existsSync
, vì vậy chúng tôi có thể quay lại stat
/ statSync
hoặc lstat
/ lstatSync
)fs.access(path, fs.F_OK, function(){})
/ fs.accessSync(path, fs.F_OK)
, nhưng lưu ý rằng nếu tệp / thư mục không tồn tại, đó là lỗi; tài liệu được fs.stat
khuyến nghị sử dụng fs.access
nếu bạn cần kiểm tra sự tồn tại mà không cần mở)fs.exists()
vẫn không được dùng nữa nhưng fs.existsSync()
không còn được dùng nữa. Vì vậy, bạn có thể sử dụng nó một cách an toàn bây giờ.Bạn có thể sử dụng statSync
hoặc lstatSync
( liên kết tài liệu ), cung cấp cho bạn một fs.Stats
đối tượng . Nói chung, nếu có phiên bản đồng bộ của chức năng, nó sẽ có cùng tên với phiên bản không đồng bộ Sync
ở cuối. Vậy statSync
là phiên bản đồng bộ của stat
; lstatSync
là phiên bản đồng bộ của lstat
, v.v.
lstatSync
cho bạn biết cả hai có tồn tại hay không, và nếu vậy, cho dù đó là tệp hoặc thư mục (hoặc trong một số hệ thống tệp, liên kết tượng trưng, thiết bị khối, thiết bị ký tự, v.v.), ví dụ: nếu bạn cần biết nếu nó tồn tại và là một thư mục:
var fs = require('fs');
try {
// Query the entry
stats = fs.lstatSync('/the/path');
// Is it a directory?
if (stats.isDirectory()) {
// Yes it is
}
}
catch (e) {
// ...
}
... và tương tự, nếu đó là một tập tin, có isFile
; nếu đó là một thiết bị khối, có isBlockDevice
, v.v. Lưu ý try/catch
; nó sẽ báo lỗi nếu mục đó hoàn toàn không tồn tại.
Nếu bạn không quan tâm mục nhập là gì và chỉ muốn biết liệu nó có tồn tại hay không, bạn có thể sử dụng path.existsSync
(hoặc mới nhất fs.existsSync
) , như ghi chú của user618408 :
var path = require('path');
if (path.existsSync("/the/path")) { // or fs.existsSync
// ...
}
Nó không yêu cầu try/catch
nhưng không cung cấp cho bạn thông tin gì về sự việc, chỉ là nó ở đó. path.existsSync
đã bị từ chối từ lâu.
Lưu ý bên lề: Bạn đã hỏi rõ ràng cách kiểm tra đồng bộ , vì vậy tôi đã sử dụng các xyzSync
phiên bản của các chức năng trên. Nhưng bất cứ nơi nào có thể, với I / O, tốt nhất là tránh các cuộc gọi đồng bộ. Các cuộc gọi vào hệ thống con I / O mất nhiều thời gian từ quan điểm của CPU. Lưu ý cách gọi dễ dàng lstat
hơn là lstatSync
:
// Is it a directory?
lstat('/the/path', function(err, stats) {
if (!err && stats.isDirectory()) {
// Yes it is
}
});
Nhưng nếu bạn cần phiên bản đồng bộ, nó sẽ ở đó.
Câu trả lời dưới đây từ một vài năm trước đây đã lỗi thời một chút. Cách hiện tại là sử dụng fs.existsSync
để thực hiện kiểm tra đồng bộ về sự tồn tại của tệp / thư mục (hoặc tất nhiên fs.exists
đối với kiểm tra không đồng bộ), thay vì các path
phiên bản bên dưới.
Thí dụ:
var fs = require('fs');
if (fs.existsSync(path)) {
// Do something
}
// Or
fs.exists(path, function(exists) {
if (exists) {
// Do something
}
});
Và đây là năm 2015 và các tài liệu Node nói rằng fs.existsSync
(và fs.exists
) "sẽ không được chấp nhận". (Bởi vì người Node nghĩ rằng thật ngu ngốc khi kiểm tra xem có thứ gì tồn tại trước khi mở hay không, nhưng đó không phải là lý do duy nhất để kiểm tra xem có thứ gì tồn tại không!)
Vì vậy, có lẽ chúng tôi quay lại các stat
phương pháp khác nhau ... Tất nhiên cho đến khi / trừ khi điều này thay đổi một lần nữa.
Không biết nó đã ở đó bao lâu, nhưng cũng có fs.access(path, fs.F_OK, ...)
/fs.accessSync(path, fs.F_OK)
. Và ít nhất là vào tháng 10 năm 2016, fs.stat
tài liệu khuyên bạn nên sử dụng fs.access
để kiểm tra sự tồn tại ( "Để kiểm tra xem một tệp có tồn tại mà không thao tác sau đó hay không, fs.access()
được khuyến nghị." ). Nhưng lưu ý rằng quyền truy cập không khả dụng được coi là một lỗi , vì vậy điều này có thể là tốt nhất nếu bạn đang mong đợi tệp có thể truy cập được:
var fs = require('fs');
try {
fs.accessSync(path, fs.F_OK);
// Do something
} catch (e) {
// It isn't accessible
}
// Or
fs.access(path, fs.F_OK, function(err) {
if (!err) {
// Do something
} else {
// It isn't accessible
}
});
Bạn có thể sử dụng fs.existsSync()
:
if (fs.existsSync(path)) {
// Do something
}
Nó đã bị phản đối trong vài năm, nhưng không còn nữa. Từ các tài liệu:
Lưu ý rằng
fs.exists()
không được chấp nhận, nhưngfs.existsSync()
không. (Tham số gọi lại đểfs.exists()
chấp nhận các tham số không phù hợp với các cuộc gọi lại Node.js khác.fs.existsSync()
Không sử dụng gọi lại.)
open
cuộc gọi và xử lý ngoại lệ hoặc bất cứ điều gì nếu tệp không tìm. Rốt cuộc, thế giới thực là hỗn loạn: Nếu bạn kiểm tra trước và nó ở đó, điều đó không có nghĩa là nó sẽ vẫn ở đó khi bạn cố gắng mở nó; nếu bạn kiểm tra trước và nó không ở đó, điều đó không có nghĩa là nó sẽ không ở đó một lát sau. Thời gian điều như vậy có vẻ như trường hợp cạnh, nhưng họ đưa ra tất cả các thời gian . Vì vậy, nếu bạn sẽ mở, không có điểm nào trong việc kiểm tra trước.
Nhìn vào nguồn, có một phiên bản đồng bộ của path.exists
- path.existsSync
. Có vẻ như nó đã bị bỏ lỡ trong các tài liệu.
path.exists
và path.existsSync
hiện đang bị phản đối . Vui lòng sử dụng .fs.exists
vàfs.existsSync
fs.exists
và bị phản đối . Sử dụng fs.stat () hoặc fs.access () để thay thế.fs.existsSync
tôi cũng đã
sử dụng fs.existsSync
. Nó không bị phản đối.
https://nodejs.org/api/fs.html#fs_fs_existssync_path
fs.existsSync
.
exists
chức năng cũ :is-there
fs.exists
là không dùng nữa trong khi fs.existsSync
không!
Sử dụng API hiện được đề xuất (kể từ năm 2015) (theo tài liệu Node), đây là những gì tôi làm:
var fs = require('fs');
function fileExists(filePath)
{
try
{
return fs.statSync(filePath).isFile();
}
catch (err)
{
return false;
}
}
Đáp lại vấn đề EPERM do @broadband nêu ra trong các bình luận, điều đó mang đến một điểm tốt. fileExists () có lẽ không phải là một cách tốt để suy nghĩ về điều này trong nhiều trường hợp, bởi vì fileExists () không thực sự hứa hẹn trả lại boolean. Bạn có thể xác định chắc chắn rằng tệp tồn tại hoặc không tồn tại, nhưng bạn cũng có thể gặp lỗi về quyền. Lỗi quyền không nhất thiết ngụ ý rằng tệp tồn tại, vì bạn có thể thiếu quyền đối với thư mục chứa tệp mà bạn đang kiểm tra. Và tất nhiên, có khả năng bạn có thể gặp một số lỗi khác trong việc kiểm tra sự tồn tại của tệp.
Vì vậy, mã của tôi ở trên thực sự làFileExistAndDoIHaveAccessToIt (), nhưng câu hỏi của bạn có thể làFileNotExistAndCouldICreateIt (), đó sẽ là logic hoàn toàn khác (cần phải tính đến lỗi EPERM, trong số những điều khác).
Mặc dù câu trả lời fs.existsSync giải quyết trực tiếp câu hỏi được hỏi ở đây, nhưng đó thường không phải là điều bạn muốn (bạn không muốn biết liệu "cái gì đó" có tồn tại trên một con đường hay không, bạn có thể quan tâm đến việc "thứ" tồn tại là một tập tin hoặc một thư mục).
Điểm mấu chốt là nếu bạn đang kiểm tra xem một tập tin có tồn tại hay không, có lẽ bạn đang làm điều đó bởi vì bạn dự định thực hiện một số hành động dựa trên kết quả và logic đó (kiểm tra và / hoặc hành động tiếp theo) sẽ phù hợp với ý tưởng rằng một thứ được tìm thấy ở đường dẫn đó có thể là một tệp hoặc một thư mục và bạn có thể gặp phải lỗi EPERM hoặc các lỗi khác trong quá trình kiểm tra.
file.exists()
cho 3% và thay vào đó buộc chúng tôi phải bọc nó trong một lần thử? Nhận thực ... Bitch của ngày.
Cập nhật khác
Cần một câu trả lời cho câu hỏi này, tôi đã tra cứu các tài liệu nút, có vẻ như bạn không nên sử dụng fs.exists, thay vào đó hãy sử dụng fs.open và sử dụng lỗi xuất ra để phát hiện nếu một tệp không tồn tại:
từ các tài liệu:
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 ở đó.
Tôi sử dụng chức năng dưới đây để kiểm tra nếu tập tin tồn tại. Nó cũng bắt ngoại lệ khác. Vì vậy, trong trường hợp có các vấn đề về quyền, ví dụ chmod ugo-rwx filename
hoặc trong Right Click -> Properties -> Security -> Advanced -> Permission entries: empty list ..
chức năng Windows
trả về ngoại lệ như bình thường. Các tập tin tồn tại nhưng chúng tôi không có quyền truy cập nó. Sẽ là sai lầm nếu bỏ qua các loại ngoại lệ này.
function fileExists(path) {
try {
return fs.statSync(path).isFile();
}
catch (e) {
if (e.code == 'ENOENT') { // no such file or directory. File really does not exist
console.log("File does not exist.");
return false;
}
console.log("Exception fs.statSync (" + path + "): " + e);
throw e; // something else went wrong, we don't have rights, ...
}
}
Đầu ra ngoại lệ, tài liệu lỗi của nodejs trong trường hợp tệp không tồn tại:
{
[Error: ENOENT: no such file or directory, stat 'X:\\delsdfsdf.txt']
errno: -4058,
code: 'ENOENT',
syscall: 'stat',
path: 'X:\\delsdfsdf.txt'
}
Ngoại lệ trong trường hợp chúng tôi không có quyền đối với tệp, nhưng tồn tại:
{
[Error: EPERM: operation not permitted, stat 'X:\file.txt']
errno: -4048,
code: 'EPERM',
syscall: 'stat',
path: 'X:\\file.txt'
}
fs.exists () không được dùng nữa https://nodejs.org/api/fs.html#fs_fs_exists_path_callback
Bạn có thể triển khai cách thức nodejs cốt lõi được sử dụng tại đây: https://github.com/nodejs/node-v0.x-archive/blob/master/lib/module.js#L86
function statPath(path) {
try {
return fs.statSync(path);
} catch (ex) {}
return false;
}
điều này sẽ trả về đối tượng thống kê sau đó khi bạn đã có đối tượng thống kê bạn có thể thử
var exist = statPath('/path/to/your/file.js');
if(exist && exist.isFile()) {
// do something
}
Một số câu trả lời ở đây nói rằng fs.exists
và fs.existsSync
cả hai đều không được chấp nhận. Theo các tài liệu thì điều này không còn đúng nữa. Chỉ fs.exists
được phát hiện ngay bây giờ:
Lưu ý rằng fs.exists () không được dùng nữa, nhưng fs.existsSync () thì không. (Tham số gọi lại cho fs.exists () chấp nhận các tham số không phù hợp với các cuộc gọi lại Node.js khác. Fs.existsSync () không sử dụng gọi lại.)
Vì vậy, bạn có thể sử dụng fs.existsSync () một cách an toàn để kiểm tra đồng bộ nếu một tệp tồn tại.
Các path
mô-đun không cung cấp một phiên bản đồng bộ path.exists
, do đó bạn phải đánh lừa xung quanh với các fs
mô-đun.
Điều nhanh nhất tôi có thể tưởng tượng là sử dụng fs.realpathSync
sẽ gây ra lỗi mà bạn phải bắt, do đó bạn cần phải thực hiện chức năng trình bao bọc của riêng mình bằng một lần thử / bắt.
Sử dụng kiểm tra fileSystem (fs) sẽ kích hoạt các đối tượng lỗi, sau đó bạn sẽ cần phải bọc trong một câu lệnh try / Catch. Hãy tiết kiệm cho mình một số nỗ lực và sử dụng một tính năng giới thiệu trong nhánh 0.4.x.
var path = require('path');
var dirs = ['one', 'two', 'three'];
dirs.map(function(dir) {
path.exists(dir, function(exists) {
var message = (exists) ? dir + ': is a directory' : dir + ': is not a directory';
console.log(message);
});
});
Các tài liệu trên fs.stat()
nói sẽ sử dụng fs.access()
nếu bạn không thao tác với tệp. Nó không đưa ra một lời biện minh, có thể là sử dụng nhanh hơn hoặc ít hơn?
Tôi sử dụng nút để tự động hóa tuyến tính, vì vậy tôi nghĩ rằng tôi chia sẻ chức năng tôi sử dụng để kiểm tra sự tồn tại của tệp.
var fs = require("fs");
function exists(path){
//Remember file access time will slow your program.
try{
fs.accessSync(path);
} catch (err){
return false;
}
return true;
}
cập nhật asnwer cho những người 'chính xác' chỉ ra rằng nó không trả lời trực tiếp câu hỏi, hơn nữa mang đến một lựa chọn thay thế.
fs.existsSync('filePath')
cũng xem tài liệu ở đây .
Trả về true nếu đường dẫn tồn tại, sai khác.
Trong ngữ cảnh không đồng bộ, bạn chỉ có thể viết phiên bản async theo phương thức đồng bộ hóa bằng cách sử dụng await
từ khóa. Bạn chỉ có thể biến phương thức gọi lại async thành một lời hứa như thế này:
function fileExists(path){
return new Promise((resolve, fail) => fs.access(path, fs.constants.F_OK,
(err, result) => err ? fail(err) : resolve(result))
//F_OK checks if file is visible, is default does no need to be specified.
}
async function doSomething() {
var exists = await fileExists('filePath');
if(exists){
console.log('file exists');
}
}
các tài liệu về quyền truy cập ().
function asyncFileExists(path) { //F_OK checks if file is visible, is default does no need to be specified. return new Promise(function (res, rej) { fs.access( path, fs.constants.F_OK, function (err) { err ? rej(err) : res(true); }, ); }); }
Rất có thể, nếu bạn muốn biết nếu một tập tin tồn tại, bạn có kế hoạch yêu cầu nó nếu nó có.
function getFile(path){
try{
return require(path);
}catch(e){
return false;
}
}
Đây là một giải pháp bao bọc đơn giản cho việc này:
var fs = require('fs')
function getFileRealPath(s){
try {return fs.realpathSync(s);} catch(e){return false;}
}
Sử dụng:
Thí dụ:
var realPath,pathToCheck='<your_dir_or_file>'
if( (realPath=getFileRealPath(pathToCheck)) === false){
console.log('file/dir not found: '+pathToCheck);
} else {
console.log('file/dir exists: '+realPath);
}
Đảm bảo bạn sử dụng toán tử === để kiểm tra nếu trả về bằng sai. Không có lý do logic nào mà fs.realpathSync () sẽ trả về false trong điều kiện làm việc phù hợp vì vậy tôi nghĩ rằng điều này sẽ hoạt động 100%.
Tôi muốn thấy một giải pháp không tạo ra Lỗi và dẫn đến hiệu quả. Từ góc độ API, fs.exists () có vẻ như là giải pháp thanh lịch nhất.
Từ các câu trả lời, có vẻ như không có hỗ trợ API chính thức nào cho việc này (như trong kiểm tra trực tiếp và rõ ràng). Nhiều câu trả lời cho biết sử dụng stat, tuy nhiên chúng không nghiêm ngặt. Ví dụ, chúng tôi không thể giả sử rằng bất kỳ lỗi nào được ném bởi stat có nghĩa là một cái gì đó không tồn tại.
Hãy nói rằng chúng tôi thử nó với một cái gì đó không tồn tại:
$ node -e 'require("fs").stat("god",err=>console.log(err))'
{ Error: ENOENT: no such file or directory, stat 'god' errno: -2, code: 'ENOENT', syscall: 'stat', path: 'god' }
Hãy thử nó với một cái gì đó tồn tại nhưng chúng ta không có quyền truy cập:
$ mkdir -p fsm/appendage && sudo chmod 0 fsm
$ node -e 'require("fs").stat("fsm/appendage",err=>console.log(err))'
{ Error: EACCES: permission denied, stat 'access/access' errno: -13, code: 'EACCES', syscall: 'stat', path: 'fsm/appendage' }
Ít nhất bạn sẽ muốn:
let dir_exists = async path => {
let stat;
try {
stat = await (new Promise(
(resolve, reject) => require('fs').stat(path,
(err, result) => err ? reject(err) : resolve(result))
));
}
catch(e) {
if(e.code === 'ENOENT') return false;
throw e;
}
if(!stat.isDirectory())
throw new Error('Not a directory.');
return true;
};
Câu hỏi không rõ ràng nếu bạn thực sự muốn nó được đồng bộ hóa hay nếu bạn chỉ muốn nó được viết như thể nó là đồng bộ. Ví dụ này sử dụng await / async để nó chỉ được viết đồng bộ nhưng chạy không đồng bộ.
Điều này có nghĩa là bạn phải gọi nó như vậy ở cấp cao nhất:
(async () => {
try {
console.log(await dir_exists('god'));
console.log(await dir_exists('fsm/appendage'));
}
catch(e) {
console.log(e);
}
})();
Một cách khác là sử dụng .then và .catch cho lời hứa được trả về từ cuộc gọi không đồng bộ nếu bạn cần tiếp tục.
Nếu bạn muốn kiểm tra xem có thứ gì đó tồn tại hay không thì cũng nên đảm bảo đó là loại vật phù hợp như thư mục hoặc tệp. Điều này được bao gồm trong ví dụ. Nếu nó không được phép là một liên kết tượng trưng, bạn phải sử dụng lstat thay vì stat vì stat sẽ tự động duyệt qua các liên kết.
Bạn có thể thay thế tất cả các async để đồng bộ mã ở đây và sử dụng statSync thay thế. Tuy nhiên, hy vọng rằng một khi async và chờ đợi trở thành hỗ trợ chung, các cuộc gọi Sync sẽ trở nên dư thừa cuối cùng sẽ bị khấu hao (nếu không, bạn sẽ phải xác định chúng ở mọi nơi và lên chuỗi giống như với async khiến nó thực sự vô nghĩa).