Node.js kiểm tra nếu tệp tồn tại


143

Làm thế nào để tôi kiểm tra sự tồn tại của một tập tin ?

Trong tài liệu cho mô-đun fscó mô tả về phương pháp fs.exists(path, callback). Nhưng, theo tôi hiểu, nó kiểm tra sự tồn tại của các thư mục duy nhất. Và tôi cần kiểm tra tập tin !

Điều này có thể giải quyết như thế nào?


3
Kể từ năm 2018, hãy sử dụng fs.access('file', err => err ? 'does not exist' : 'exists'), xem fs.access
mb21

Câu trả lời:


227

Tại sao không thử mở tập tin? fs.open('YourFile', 'a', function (err, fd) { ... }) dù sao sau một phút tìm kiếm hãy thử điều này:

var path = require('path'); 

path.exists('foo.txt', function(exists) { 
  if (exists) { 
    // do something 
  } 
}); 

// or 

if (path.existsSync('foo.txt')) { 
  // do something 
} 

Đối với Node.js v0.12.x trở lên

Cả hai path.existsfs.existsđã bị từ chối

*Biên tập:

Thay đổi: else if(err.code == 'ENOENT')

đến: else if(err.code === 'ENOENT')

Linter phàn nàn về việc hai bằng không phải là ba bằng.

Sử dụng fs.stat:

fs.stat('foo.txt', function(err, stat) {
    if(err == null) {
        console.log('File exists');
    } else if(err.code === 'ENOENT') {
        // file does not exist
        fs.writeFile('log.txt', 'Some log\n');
    } else {
        console.log('Some other error: ', err.code);
    }
});

1
Nhưng, hóa ra, fs.existsnó cũng hoạt động. Tôi đã có vấn đề với quyền cho tập tin.
RomanGorbatko

11
path.existsthực sự không được ủng hộfs.exists
Arnaud Rinquin

42
Bất cứ ai đang đọc điều này bây giờ (Node.js v0.12.x) hãy ghi nhớ điều đó fs.existsfs.existsSynccũng đã bị phản đối. Cách tốt nhất để kiểm tra sự tồn tại của tập tin là fs.stat, như đã trình bày ở trên.
Antrikshy

8
Từ tài liệu của Node js, có vẻ như là cách tốt nhất nếu bạn dự định mở tệp sau khi kiểm tra sự tồn tại của nó, là thực sự mở nó và xử lý các lỗi nếu nó không tồn tại. Bởi vì tệp của bạn có thể bị xóa giữa kiểm tra tồn tại của bạn và chức năng mở ...
newprog

6
@Antrikshy fs.existsSynckhông còn bị lỗi mốt nữa, mặc dù vậy fs.existsvẫn vậy .
RyanZim

52

Một cách dễ dàng hơn để làm điều này một cách đồng bộ.

if (fs.existsSync('/etc/file')) {
    console.log('Found file');
}

Tài liệu API cho biết cách thức existsSynchoạt động:
Kiểm tra xem đường dẫn đã cho có tồn tại hay không bằng cách kiểm tra với hệ thống tệp.


12
fs.existsSync(path)hiện không được chấp nhận, xem nodejs.org/api/fs.html#fs_fs_existssync_path . Để thực hiện đồng bộ fs.statSync(path)được khuyên, xem câu trả lời của tôi.
lmeurs

20
@Imeurs nhưng nodejs.org/api/fs.html#fs_fs_existssync_path nói: Lưu ý rằng fs.exists () không được dùng nữa, nhưng fs.existsSync () thì không.
HaveF

9
fs.existsSyncđã bị phản đối, nhưng nó không còn nữa.
RyanZim

44

Chỉnh sửa: Vì nút v10.0.0chúng ta có thể sử dụngfs.promises.access(...)

Ví dụ mã async kiểm tra nếu tệp tồn tại:

async function checkFileExists(file) {
  return fs.promises.access(file, fs.constants.F_OK)
           .then(() => true)
           .catch(() => false)
}

Một thay thế cho stat có thể được sử dụng mới fs.access(...):

chức năng hứa ngắn gọn để kiểm tra:

s => new Promise(r=>fs.access(s, fs.constants.F_OK, e => r(!e)))

Sử dụng mẫu:

let checkFileExists = s => new Promise(r=>fs.access(s, fs.constants.F_OK, e => r(!e)))
checkFileExists("Some File Location")
  .then(bool => console.logfile exists: ${bool}´))

cách hứa hẹn mở rộng:

// returns a promise which resolves true if file exists:
function checkFileExists(filepath){
  return new Promise((resolve, reject) => {
    fs.access(filepath, fs.constants.F_OK, error => {
      resolve(!error);
    });
  });
}

hoặc nếu bạn muốn làm điều đó một cách đồng bộ:

function checkFileExistsSync(filepath){
  let flag = true;
  try{
    fs.accessSync(filepath, fs.constants.F_OK);
  }catch(e){
    flag = false;
  }
  return flag;
}

1
Được nâng cấp, đây chắc chắn là cách hiện đại nhất (2018) để phát hiện nếu một tệp tồn tại trong Node.js
AKMorris

1
Có, đây là phương pháp được đề xuất chính thức để kiểm tra xem tập tin có tồn tại hay không và thao tác sau đó không được mong đợi. Nếu không, sử dụng mở / ghi / đọc và xử lý lỗi. nodejs.org/api/fs.html#fs_fs_stat_path_callback
Justin

1
Trong tài liệu tôi tìm thấy, fs.constants.F_OKvv Cũng có thể truy cập chúng như thế fs.F_OKnào? Kỳ dị. Cũng ngắn gọn, đó là tốt đẹp.
samson

1
Có thể thử thực hiện với fs.promises.access(path, fs.constants.F_OK);chỉ đơn giản là biến nó thành Lời hứa thay vì tạo Lời hứa.
Jeremy Trpka

18

fs.exists(path, callback)fs.existsSync(path)không được chấp nhận ngay bây giờ, hãy xem https://nodejs.org/api/fs.html#fs_fs_exists_path_callbackhttps://nodejs.org/api/fs.html#fs_fs_existssync_path .

Để kiểm tra sự tồn tại của một tệp một cách đồng bộ, người ta có thể sử dụng tức là. fs.statSync(path). Một fs.Statsđối tượng sẽ được trả về nếu tệp tồn tại, xem https://nodejs.org/api/fs.html#fs_group_fs_stats , nếu không, một lỗi sẽ được đưa ra bởi câu lệnh try / Catch.

var fs = require('fs'),
  path = '/path/to/my/file',
  stats;

try {
  stats = fs.statSync(path);
  console.log("File exists.");
}
catch (e) {
  console.log("File does not exist.");
}

10
Liên kết bạn cung cấp cho fs.existsync thống kê rõ ràng rằng nó KHÔNG bị phản đối "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 nhất quán với các cuộc gọi lại Node.js khác. fs.existsSync () không sử dụng cuộc gọi lại.) "
shreddish

câu trả lời đầu tiên (từ trên cùng), trong đó đề cập đến việc fsbiến đến từ đâu
Dmitry Korolyov

Tại thời điểm câu trả lời này được viết, thông tin là chính xác; tuy nhiên, fs.existsSync()không còn bị phản đối
RyanZim

12

Phiên bản cũ trước V6: đây là tài liệu

  const fs = require('fs');    
  fs.exists('/etc/passwd', (exists) => {
     console.log(exists ? 'it\'s there' : 'no passwd!');
  });
// or Sync

  if (fs.existsSync('/etc/passwd')) {
    console.log('it\'s there');
  }

CẬP NHẬT

Các phiên bản mới từ V6: tài liệu chofs.stat

fs.stat('/etc/passwd', function(err, stat) {
    if(err == null) {
        //Exist
    } else if(err.code == 'ENOENT') {
        // NO exist
    } 
});

1
Cả hai fs.existsfs.existsSynckhông được chấp nhận theo liên kết bạn đã chia sẻ.
Andy

existsSynckhông được phản đối theo tài liệu đó, có thể là khi bạn đọc nó.
Darpan

11

Async / await cách hiện đại (Nút 12.8.x)

const fileExists = async path => !!(await fs.promises.stat(path).catch(e => false));

const main = async () => {
    console.log(await fileExists('/path/myfile.txt'));
}

main();

Chúng ta cần sử dụng fs.stat() or fs.access()fs.exists(path, callback)bây giờ không dùng nữa

Một cách tốt khác là fs-thêm


7

fs.existsđã bị từ chối từ 1.0.0. Bạn có thể sử dụng fs.statthay vì đó.

var fs = require('fs');
fs.stat(path, (err, stats) => {
if ( !stats.isFile(filename) ) { // do this 
}  
else { // do this 
}});

Đây là liên kết cho tài liệu fs.stats


stats.isFile()không cần filename.
Wtower

6

@Fox: câu trả lời tuyệt vời! Đây là một phần mở rộng với một số tùy chọn khác. Đó là những gì tôi đã sử dụng gần đây như một giải pháp đi tới:

var fs = require('fs');

fs.lstat( targetPath, function (err, inodeStatus) {
  if (err) {

    // file does not exist-
    if (err.code === 'ENOENT' ) {
      console.log('No file or directory at',targetPath);
      return;
    }

    // miscellaneous error (e.g. permissions)
    console.error(err);
    return;
  }


  // Check if this is a file or directory
  var isDirectory = inodeStatus.isDirectory();


  // Get file size
  //
  // NOTE: this won't work recursively for directories-- see:
  // http://stackoverflow.com/a/7550430/486547
  //
  var sizeInBytes = inodeStatus.size;

  console.log(
    (isDirectory ? 'Folder' : 'File'),
    'at',targetPath,
    'is',sizeInBytes,'bytes.'
  );


}

PS hãy kiểm tra fs-Extra nếu bạn chưa sử dụng nó - nó khá ngọt. https://github.com/jprichardson/node-fs-extra )



3

async/awaitphiên bản sử dụng util.promisifynhư của Nút 8:

const fs = require('fs');
const { promisify } = require('util');
const stat = promisify(fs.stat);

describe('async stat', () => {
  it('should not throw if file does exist', async () => {
    try {
      const stats = await stat(path.join('path', 'to', 'existingfile.txt'));
      assert.notEqual(stats, null);
    } catch (err) {
      // shouldn't happen
    }
  });
});

describe('async stat', () => {
  it('should throw if file does not exist', async () => {
    try {
      const stats = await stat(path.join('path', 'to', 'not', 'existingfile.txt'));
    } catch (err) {
      assert.notEqual(err, null);
    }
  });
});

2
  fs.statSync(path, function(err, stat){
      if(err == null) {
          console.log('File exists');
          //code when all ok
      }else if (err.code == "ENOENT") {
        //file doesn't exist
        console.log('not file');

      }
      else {
        console.log('Some other error: ', err.code);
      }
    });

2

Sau một chút thử nghiệm, tôi thấy ví dụ sau sử dụng fs.statlà một cách tốt để kiểm tra không đồng bộ một tệp có tồn tại hay không. Nó cũng kiểm tra xem "tập tin" của bạn có phải là "tập tin thực sự" (và không phải là một thư mục).

Phương pháp này sử dụng Promise, giả sử rằng bạn đang làm việc với một cơ sở mã không đồng bộ:

const fileExists = path => {
  return new Promise((resolve, reject) => {
    try {
      fs.stat(path, (error, file) => {
        if (!error && file.isFile()) {
          return resolve(true);
        }

        if (error && error.code === 'ENOENT') {
          return resolve(false);
        }
      });
    } catch (err) {
      reject(err);
    }
  });
};

Nếu tập tin không tồn tại, lời hứa vẫn giải quyết, mặc dù false. Nếu tập tin tồn tại và nó là một thư mục, thì nó sẽ được giải quyết true. Bất kỳ lỗi nào cố gắng đọc tệp sẽ rejecthứa với chính lỗi đó.


1

Vâng, tôi đã làm theo cách này, như đã thấy trên https://nodejs.org/api/fs.html#fs_fs_access_path_mode_callback

fs.access('./settings', fs.constants.F_OK | fs.constants.R_OK | fs.constants.W_OK, function(err){
  console.log(err ? 'no access or dir doesnt exist' : 'R/W ok');

  if(err && err.code === 'ENOENT'){
    fs.mkdir('settings');
  }
});

Có bất kỳ vấn đề với điều này?


0

ngày xưa trước khi ngồi xuống tôi luôn kiểm tra xem ghế có ở đó không thì tôi ngồi khác tôi có kế hoạch thay thế như ngồi trên xe khách. Bây giờ trang web node.js đề xuất chỉ cần đi (không cần kiểm tra) và câu trả lời trông như thế này:

    fs.readFile( '/foo.txt', function( err, data )
    {
      if(err) 
      {
        if( err.code === 'ENOENT' )
        {
            console.log( 'File Doesn\'t Exist' );
            return;
        }
        if( err.code === 'EACCES' )
        {
            console.log( 'No Permission' );
            return;
        }       
        console.log( 'Unknown Error' );
        return;
      }
      console.log( data );
    } );

mã được lấy từ http://fredkschott.com/post/2014/03/under Hiểu-Ferror-first-callbacks-in-node-js / từ tháng 3 năm 2014 và sửa đổi một chút để phù hợp với máy tính. Nó cũng kiểm tra sự cho phép - loại bỏ quyền kiểm trachmod a-r foo.txt


0

gọi lại vannilla Nodejs

function fileExists(path, cb){
  return fs.access(path, fs.constants.F_OK,(er, result)=> cb(!err && result)) //F_OK checks if file is visible, is default does no need to be specified.
}

các tài liệu nói rằng bạn nên sử dụng access()như là một thay thế cho không dùng nữaexists()

Nodejs với lời hứa xây dựng (nút 7+)

function fileExists(path, cb){
  return new Promise((accept,deny) => 
    fs.access(path, fs.constants.F_OK,(er, result)=> cb(!err && result))
  );
}

Khung javascript phổ biến

fs-thêm

var fs = require('fs-extra')
await fs.pathExists(filepath)

Như bạn thấy đơn giản hơn nhiều. Và lợi thế hơn cả là bạn có các kiểu đánh máy hoàn chỉnh với gói này (hoàn thành intellisense / typecript)! Hầu hết các trường hợp bạn sẽ bao gồm thư viện này vì (+ -10.000) thư viện khác phụ thuộc vào thư viện.


0

Bạn có thể sử dụng fs.statđể kiểm tra xem đích có phải là tệp hoặc thư mục không và bạn có thể sử dụng fs.accessđể kiểm tra xem bạn có thể ghi / đọc / thực thi tệp không. (nhớ sử dụngpath.resolve để có được đường dẫn đầy đủ cho mục tiêu)

Tài liệu:

Ví dụ đầy đủ (TypeScript)

import * as fs from 'fs';
import * as path from 'path';

const targetPath = path.resolve(process.argv[2]);

function statExists(checkPath): Promise<fs.Stats> {
  return new Promise((resolve) => {
    fs.stat(checkPath, (err, result) => {
      if (err) {
        return resolve(undefined);
      }

      return resolve(result);
    });
  });
}

function checkAccess(checkPath: string, mode: number = fs.constants.F_OK): Promise<boolean> {
  return new Promise((resolve) => {
    fs.access(checkPath, mode, (err) => {
      resolve(!err);
    });
  });
}

(async function () {
  const result = await statExists(targetPath);
  const accessResult = await checkAccess(targetPath, fs.constants.F_OK);
  const readResult = await checkAccess(targetPath, fs.constants.R_OK);
  const writeResult = await checkAccess(targetPath, fs.constants.W_OK);
  const executeResult = await checkAccess(targetPath, fs.constants.X_OK);
  const allAccessResult = await checkAccess(targetPath, fs.constants.F_OK | fs.constants.R_OK | fs.constants.W_OK | fs.constants.X_OK);

  if (result) {
    console.group('stat');
    console.log('isFile: ', result.isFile());
    console.log('isDir: ', result.isDirectory());
    console.groupEnd();
  }
  else {
    console.log('file/dir does not exist');
  }

  console.group('access');
  console.log('access:', accessResult);
  console.log('read access:', readResult);
  console.log('write access:', writeResult);
  console.log('execute access:', executeResult);
  console.log('all (combined) access:', allAccessResult);
  console.groupEnd();

  process.exit(0);
}());

0

Đối với phiên bản không đồng bộ! Và với phiên bản hứa! Đây là cách đơn giản sạch sẽ!

try {
    await fsPromise.stat(filePath);
    /**
     * File exists!
     */
    // do something
} catch (err) {
    if (err.code = 'ENOENT') {
        /**
        * File not found
        */
    } else {
        // Another error!
    }
}

Một đoạn thực tế hơn từ mã của tôi để minh họa rõ hơn:


try {
    const filePath = path.join(FILES_DIR, fileName);
    await fsPromise.stat(filePath);
    /**
     * File exists!
     */
    const readStream = fs.createReadStream(
        filePath,
        {
            autoClose: true,
            start: 0
        }
    );

    return {
        success: true,
        readStream
    };
} catch (err) {
    /**
     * Mapped file doesn't exists
     */
    if (err.code = 'ENOENT') {
        return {
            err: {
                msg: 'Mapped file doesn\'t exists',
                code: EErrorCode.MappedFileNotFound
            }
        };
    } else {
        return {
            err: {
                msg: 'Mapped file failed to load! File system error',
                code: EErrorCode.MappedFileFileSystemError
            }
        }; 
   }
}

Ví dụ trên chỉ là để trình diễn! Tôi có thể đã sử dụng sự kiện lỗi của luồng đọc! Để bắt bất kỳ lỗi nào! Và bỏ qua hai cuộc gọi!

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.