Kiểm tra đồng bộ nếu tệp / thư mục tồn tại trong Node.js


1209

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?


58
Các hoạt động đồng bộ là tuyệt vời để thực hiện các hoạt động tập tin / thư mục một lần trước khi trả lại một mô-đun. Ví dụ, bootstrapping một tập tin cấu hình.
vui vẻ

1
@PaulDraper với bộ đệm ấm không đúng trong mọi trường hợp.
mikemaccana

12
Bất kể hiệu suất, đôi khi bạn chỉ muốn chạy nó theo cách đồng bộ cho trải nghiệm của nhà phát triển. Ví dụ: nếu bạn đang sử dụng Node cho tập lệnh xử lý dữ liệu mà theo thiết kế sẽ bị chặn, trong trường hợp đó, async existschỉ thêm các cuộc gọi lại không cần thiết.
Kunok

3
Chắc chắn +1 cho tuyên bố của Kunok. Trong phần còn lại của mã, tôi chỉ làm cho mã phức tạp hơn khi đó là một nút cổ chai mà tốc độ thực sự quan trọng. Tại sao tôi không áp dụng nguyên tắc đó để đọc tệp? Trong nhiều phần của nhiều chương trình, tính đơn giản / dễ đọc của mã có thể quan trọng hơn tốc độ thực thi. Nếu đó là một khu vực tắc nghẽn, tôi sẽ sử dụng các phương thức không đồng bộ để tránh dừng thực thi mã tiếp theo. Nếu không ... đồng bộ hóa là tuyệt vời. Đừng mù quáng đồng bộ hóa.
BryanGrezeszak

3
Vui lòng ... không "đáng chú ý" vì người dùng hỏi rõ ràng cách thực hiện đồng bộ.
jClark

Câu trả lời:


2241

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:

Câu trả lời hiện tại

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ưng fs.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.accessnếu bạn đang sử dụng các asyncchức năng hoặc fs.access(vì existskhông được dùng nữa ) nếu không:

Trong một asyncchứ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
    }
});

Câu trả lời lịch sử

Dưới đây là các câu trả lời lịch sử theo thứ tự thời gian:

  • Câu trả lời gốc từ năm 2010
    ( stat/ statSynchoặc lstat/ lstatSync)
  • Cập nhật tháng 9 năm 2012
    ( exists/ existsSync)
  • Cập nhật tháng 2 năm 2015
    (Lưu ý sự phản đối sắp xảy ra của exists/ existsSync, vì vậy chúng tôi có thể quay lại stat/ statSynchoặc lstat/ lstatSync)
  • Cập nhật tháng 12 năm 2015
    (Cũng có 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.statkhuyến nghị sử dụng fs.accessnếu bạn cần kiểm tra sự tồn tại mà không cần mở)
  • Cập nhật tháng 12 năm 2016
    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ờ.

Câu trả lời gốc từ năm 2010:

Bạn có thể sử dụng statSynchoặ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 statSynclà phiên bản đồng bộ của stat; lstatSynclà 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/catchnhư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 xyzSyncphiê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 lstathơ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ập nhật tháng 9 năm 2012

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 pathphiê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
    }
});

Cập nhật tháng 2 năm 2015

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 statphươ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.

Cập nhật tháng 12 năm 2015

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.stattà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
    }
});

Cập nhật tháng 12 năm 2016

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ưng fs.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.)


7
path.exists và path.existsSync đều đã được phản đối ủng hộ fs.exists và fs.existsSync
Drew

15
"Mọi người nghĩ rằng thật ngu ngốc khi kiểm tra xem có thứ gì tồn tại trước khi mở nó hay không;" Tại sao nó câm để kiểm tra nếu tập tin tồn tại?
Petr Hurtak

32
@PetrHurtak: Không phải lúc nào cũng vậy (vì có rất nhiều lý do để kiểm tra sự tồn tại), nhưng nếu bạn sẽ mở tệp, tốt nhất là chỉ thực hiện opencuộ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.
TJ Crowder

13
Và ở đây tôi nghĩ rằng đó là một kiểu chống sử dụng lỗi cho luồng điều khiển: link
argyle

4
@jeromeyer: Bạn có thể, nhưng Ionică đã làm điều đó cho bạn (xem bình luận ở trên ). :-)
TJ Crowder

124

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.

Cập nhật:

path.existspath.existsSynchiện đang bị phản đối . Vui lòng sử dụng fs.existsfs.existsSync .

Cập nhật 2016:

fs.exists fs.existsSynctôi cũng đã bị phản đối . Sử dụng fs.stat () hoặc fs.access () để thay thế.

Cập nhật 2019:

sử dụng fs.existsSync. Nó không bị phản đối. https://nodejs.org/api/fs.html#fs_fs_existssync_path


1
path.existsSync (p) nằm trong 0.4.10 docs nodejs.org/docs/v0.4.10/api/path.html
Paul Beusterien

21
Trên thực tế, một câu trả lời gần đây hơn: path.existsSync không được dùng nữa. Bây giờ nó được gọi là fs.existsSync.
Olivier Lalonde

9
Bây giờ các tài liệu đang nói fs.exists sẽ bị phản đối. nodejs.org/api/fs.html#fs_fs_existssync_path
Greg Hornby

Tôi đã viết một thư viện nhỏ để thay thế existschức năng cũ :is-there
Ionică Bizău

6
tài liệu hiện tại (phiên bản ~ 9) chỉ được dán nhãn fs.existslà không dùng nữa trong khi fs.existsSynckhông!
Kunok

57

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.


4
Đẹp, tôi đã thêm | | isDirectory () để làm cho nó một trình kiểm tra tệp / thư mục. var stats = fs.statSync (filePath); return stats.isFile () || stats.isDirectory ();
bob

4
Nếu chương trình không có quyền truy cập tệp, nó vẫn trả về sai mặc dù tệp tồn tại tức là xóa tất cả các phần cứng khỏi tệp chmod ugo-rwx file.txt hoặc trong Windows Nhấp chuột phải ... Thông báo ngoại lệ: Ngoại lệ fs.statSync (./ f.txt): Lỗi: EPERM: hoạt động không được phép, stat 'X: \ f.txt'. Vì vậy, trường hợp này không được bao phủ bởi mã trên.
băng thông rộng

2
Wow, đôi khi bị chậm lại. Vì vậy, chắc chắn, 97% thời gian bạn sẽ sử dụng tệp, nhưng không sử dụng đơn giản 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.
trục xuất

20

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 ở đó.

http://nodejs.org/api/fs.html#fs_fs_exists_path_callback


1
có cách nào để làm điều đó với openSync, thay vì mở
Greg Hornby

1
@GregHornby Tôi tưởng tượng nó sẽ hoạt động theo cùng một cách với openSync
Melbourne2991

2
Đối với những người vẫn cần existsexistsSynctôi đã tạo ra is-there.
Ionică Bizău

6
Sự phản đối này làm phiền tôi Mở tệp chỉ để xem lỗi có bị ném hay không có vẻ như lãng phí tài nguyên khi tất cả những gì cần thiết là kiến ​​thức về sự tồn tại của tệp.
Josh Hansen

11

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 filenamehoặ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'
}

2
Thực sự thích điều này, đó là một trong số ít câu trả lời được cập nhật kể từ khi nút không chấp nhận 37 cách cuối cùng để thực hiện việc này
1mike12

Bah, bạn đánh tôi với nó Tôi có thể đã tiết kiệm thời gian nếu tôi đã đọc nó.
jgmjgm

5

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
}

4

Một số câu trả lời ở đây nói rằng fs.existsfs.existsSynccả 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.


3

Các pathmô-đ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 fsmô-đun.

Điều nhanh nhất tôi có thể tưởng tượng là sử dụng fs.realpathSyncsẽ 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.


1

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);
  });
});

2
Path.exists hiện nằm dưới fs, vì vậy nó là fs.exists (path, callback)
Todd Moses

0

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;
}

0

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ế.

Giải pháp đồng bộ hóa:

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.

Giải pháp Async Promise

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 awaittừ 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 ().


1
OP muốn một giải pháp đồng bộ
vdegenne

bạn nên cập nhật mã của mình lênfunction 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); }, ); }); }
pery mimon

0

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;
    }
}

-1

Đâ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:

  • Hoạt động cho cả thư mục và tập tin
  • Nếu mục tồn tại, nó trả về đường dẫn đến tệp hoặc thư mục
  • Nếu mục không tồn tại, nó trả về false

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.


1
@Dan, cảm ơn. Tôi loại bỏ văn bản cắt ngắn. Tôi không thể nhớ lại những gì đã được ghi chú. Nếu nó đến tôi sẽ thêm ghi chú.
Timothy C. Quinn

1
Np. Tôi đang xóa bình luận của tôi.
Dan Dascalescu

-2

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).


1
Câu hỏi ban đầu không chỉ định điều đó. Tôi cũng đang chứng minh làm thế nào để làm mọi thứ rõ ràng. Nhiều câu trả lời có thể gây ra lỗi do thiếu rõ ràng. Mọi người thường muốn lập trình mọi thứ để nó xuất hiện đồng bộ nhưng không nhất thiết muốn thực thi đồng bộ. statSync không giống với mã tôi đã trình bày. Tài khoản của những gì thực sự mong muốn là mơ hồ, vì vậy bạn chỉ áp đặt các diễn giải cá nhân của bạn. Nếu bạn tìm thấy câu trả lời mà bạn không hiểu, có thể tốt hơn là chỉ cần hỏi trong các bình luận hoặc PM để tìm ra những chỉnh sửa nào là cần thiết.
jgmjgm

1
Nếu bạn muốn, bạn cũng có thể lấy cắp mẫu mã của tôi, đặt tên cho nó một cách thích hợp, đặt nó trên github, thêm nó vào npm và sau đó câu trả lời sẽ chỉ là một dòng / liên kết: D.
jgmjgm

Mã này là ví dụ ngắn gọn, nhưng bạn có thể gửi đề xuất chỉnh sửa để bao gồm &&! IsFile hoặc kiểm tra các liên kết tượng trưng, ​​v.v. (một lần nữa mặc dù câu hỏi không bao giờ nêu rõ đó là điều họ muốn). Như tôi đã chỉ ra câu trả lời của tôi thỏa mãn một cách giải thích câu hỏi và không làm điều tương tự như đề xuất một dòng của bạn.
jgmjgm
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.