Node.js ตรวจสอบว่ามีไฟล์อยู่หรือไม่


143

ฉันจะตรวจสอบการมีอยู่ของไฟล์ได้อย่างไร?

ในเอกสารสำหรับโมดูลมีรายละเอียดของวิธีการที่fs fs.exists(path, callback)แต่ที่ฉันเข้าใจมันตรวจสอบการมีอยู่ของไดเรกทอรีเท่านั้น และฉันต้องตรวจสอบไฟล์ !

สิ่งนี้สามารถทำได้?


3
ตั้งแต่วันที่ 2018 ใช้fs.access('file', err => err ? 'does not exist' : 'exists')ดูfs.access
mb21

คำตอบ:


227

ทำไมไม่ลองเปิดไฟล์ดูล่ะ? fs.open('YourFile', 'a', function (err, fd) { ... }) ต่อไปหลังจากการค้นหานาทีลองนี้:

var path = require('path'); 

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

// or 

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

สำหรับ Node.js v0.12.x และสูงกว่า

ทั้งpath.existsและfs.existsเลิกใช้แล้ว

* แก้ไข:

การเปลี่ยนแปลง: else if(err.code == 'ENOENT')

ถึง: else if(err.code === 'ENOENT')

Linter บ่นว่าสองเท่ากับไม่สามเท่ากับ

ใช้ 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
แต่เมื่อมันปรากฏออกมาก็ใช้fs.existsงานได้เช่นกัน ฉันมีปัญหากับการอนุญาตของไฟล์
RomanGorbatko

11
path.existsจริงเลิกใช้แล้วในความโปรดปรานของfs.exists
Arnaud Rinquin

42
ทุกคนที่อ่านสิ่งนี้ในตอนนี้ (Node.js v0.12.x) โปรดจำไว้ว่าfs.existsและfs.existsSyncเลิกใช้แล้ว วิธีที่ดีที่สุดในการตรวจสอบการมีอยู่ของไฟล์คือfs.statตามตัวอย่างด้านบน
Antrikshy

8
จากเอกสารของ Node js ดูเหมือนว่าวิธีที่ดีที่สุดถ้าคุณวางแผนที่จะเปิดไฟล์หลังจากตรวจสอบการมีอยู่ของมันคือการเปิดมันขึ้นมาจริง ๆ และจัดการกับข้อผิดพลาดหากไม่มีอยู่ เพราะไฟล์ของคุณจะถูกลบออกระหว่างอยู่การตรวจสอบและเปิดฟังก์ชั่น ... ของคุณ
newprog

6
@Antrikshy fs.existsSyncจะไม่ถูกคัดค้านอีกต่อไปแม้ว่าจะfs.existsยังเป็นอยู่ก็ตาม
RyanZim

52

วิธีที่ง่ายกว่าในการทำสิ่งนี้พร้อมกัน

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

API เอกสารระบุว่าexistsSyncทำงานอย่างไร:
ทดสอบว่ามีเส้นทางที่กำหนดอยู่หรือไม่โดยตรวจสอบกับระบบไฟล์


12
fs.existsSync(path)จะเลิกตอนนี้ดูnodejs.org/api/fs.html#fs_fs_existssync_path สำหรับการfs.statSync(path)แนะนำให้ใช้งานแบบซิงโครนัสดูคำตอบของฉัน
lmeurs

20
@Imeurs แต่nodejs.org/api/fs.html#fs_fs_existssync_pathพูดว่า: โปรดทราบว่า fs.exists () เลิกใช้แล้ว แต่ fs.existsSync () ไม่ใช่
HaveF

9
fs.existsSyncเลิกใช้แล้ว แต่ไม่มีอีกต่อไป
RyanZim

44

แก้ไข: เนื่องจากโหนดv10.0.0เราสามารถใช้fs.promises.access(...)

ตัวอย่างรหัส async ที่ตรวจสอบว่ามีไฟล์อยู่หรือไม่:

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

ทางเลือกสำหรับ stat อาจใช้ใหม่fs.access(...):

ฟังก์ชันย่อขนาดย่อสำหรับการตรวจสอบ:

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

ตัวอย่างการใช้งาน:

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

ขยายสัญญาทาง:

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

หรือถ้าคุณต้องการที่จะทำมันพร้อมกัน:

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

1
Upvoted นี่เป็นวิธีที่ทันสมัยที่สุด (2018) ในการตรวจสอบว่ามีไฟล์อยู่ใน Node.js หรือไม่
AKMorris

1
ใช่นี่เป็นวิธีที่แนะนำอย่างเป็นทางการในการตรวจสอบว่ามีไฟล์อยู่หรือไม่และไม่ได้รับการจัดการในภายหลัง มิฉะนั้นใช้เปิด / เขียน / อ่านและจัดการข้อผิดพลาด nodejs.org/api/fs.html#fs_fs_stat_path_callback
Justin

1
ในเอกสารที่ผมพบfs.constants.F_OKฯลฯ นอกจากนี้ยังเป็นไปได้ที่จะเข้าถึงพวกเขาเช่นfs.F_OK? แปลก. ยังสั้นซึ่งเป็นสิ่งที่ดี
แซมซั่น

1
สามารถลองทำด้วยfs.promises.access(path, fs.constants.F_OK);เพื่อให้มันเป็นสัญญาแทนการสร้างสัญญา
Jeremy Trpka

18

fs.exists(path, callback)และfs.existsSync(path)จะเลิกตอนนี้ดูhttps://nodejs.org/api/fs.html#fs_fs_exists_path_callbackและhttps://nodejs.org/api/fs.html#fs_fs_existssync_path

ในการทดสอบการมีอยู่ของไฟล์หนึ่งสามารถใช้เช่น fs.statSync(path). fs.Statsวัตถุจะถูกส่งกลับหากไฟล์ที่มีอยู่ให้ดูhttps://nodejs.org/api/fs.html#fs_class_fs_statsมิฉะนั้นข้อผิดพลาดจะถูกโยนทิ้งซึ่งจะ catched โดยลอง / คำสั่งจับ

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
ลิงก์ที่คุณระบุไว้สำหรับ fs.existsync ชัดเจนว่าไม่ได้คัดค้าน "โปรดทราบว่า fs.exists () เลิกใช้แล้ว แต่ fs.existsSync () ไม่ใช่ (พารามิเตอร์การเรียกกลับไปยัง fs.exists () ยอมรับพารามิเตอร์ที่ไม่สอดคล้องกัน กับการโทรกลับ Node.js อื่น ๆ fs.existsSync () ไม่ได้ใช้การโทรกลับ) "
shreddish

คำตอบแรก (จากด้านบน) ซึ่งกล่าวถึงว่าfsตัวแปรมาจากไหน
Dmitry Korolyov

ในขณะที่เขียนคำตอบนี้ข้อมูลถูกต้อง อย่างไรก็ตามfs.existsSync()ไม่เลิกใช้แล้ว
RyanZim

12

เวอร์ชันเก่าก่อน V6: นี่คือเอกสาร

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

UPDATE

รุ่นใหม่จาก V6: เอกสารสำหรับfs.stat

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

1
ทั้งสองfs.existsและfs.existsSyncเลิกใช้ตามลิงก์ที่คุณแบ่งปัน
แอนดี้

existsSyncไม่ได้เลิกใช้ตามเอกสารนั้นอาจเป็นเมื่อคุณอ่าน
Darpan

11

async / ทางรอทันสมัย ​​(Node 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();

เราจำเป็นต้องใช้fs.stat() or fs.access()เพราะfs.exists(path, callback)ตอนนี้เลิกใช้แล้ว

อีกวิธีที่ดีคือเอฟเอสพิเศษ


7

fs.existsเลิกใช้แล้วตั้งแต่ 1.0.0 คุณสามารถใช้fs.statแทน

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

นี่คือลิงค์สำหรับเอกสาร fs.stats


stats.isFile()filenameไม่จำเป็นต้อง
Wtower

6

@Fox: คำตอบที่ดี! ต่อไปนี้เป็นส่วนเสริมเล็กน้อยพร้อมตัวเลือกเพิ่มเติม เป็นสิ่งที่ฉันได้ใช้เมื่อเร็ว ๆ นี้เป็นวิธีแก้ปัญหาแบบไปสู่

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 ลองใช้ fs-extra ถ้าคุณยังไม่ได้ใช้มันมันช่างน่ารัก https://github.com/jprichardson/node-fs-extra )



3

async/awaitเวอร์ชันที่ใช้util.promisifyณ โหนด 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

หลังจากการทดลองเล็กน้อยฉันพบว่าตัวอย่างต่อไปนี้ใช้fs.statเป็นวิธีที่ดีในการตรวจสอบแบบอะซิงโครนัสว่ามีไฟล์อยู่หรือไม่ นอกจากนี้ยังตรวจสอบว่า "ไฟล์" ของคุณเป็น "จริงๆ -is-a-file" (และไม่ใช่ไดเรกทอรี)

วิธีนี้ใช้สัญญาโดยสมมติว่าคุณกำลังทำงานกับรหัสฐานแบบอะซิงโครนัส:

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

falseหากไฟล์ไม่ได้อยู่ที่สัญญาว่าจะยังคงแก้ไขแม้ว่า หากไฟล์นั้นมีอยู่และมันเป็นไดเรกทอรีก็จะหายtrueไป ข้อผิดพลาดใด ๆ ที่พยายามอ่านไฟล์จะrejectเป็นข้อผิดพลาด



0

ในวันก่อนที่จะนั่งลงฉันมักจะตรวจสอบว่ามีเก้าอี้อยู่หรือไม่ฉันนั่งที่อื่นฉันมีแผนสำรองเช่นนั่งบนรถโค้ช ตอนนี้เว็บไซต์ node.js แนะนำให้ไปเลย (ไม่จำเป็นต้องตรวจสอบ) และคำตอบจะเป็นดังนี้:

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

รหัสที่นำมาจากhttp://fredkschott.com/post/2014/03/understanding-error-first-callbacks-in-node-js/จากมีนาคม 2014 และปรับเปลี่ยนเล็กน้อยเพื่อให้พอดีกับคอมพิวเตอร์ ตรวจสอบการอนุญาตเช่นกัน - ลบการอนุญาตสำหรับการทดสอบchmod a-r foo.txt


0

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

เอกสารบอกว่าคุณควรจะใช้access()แทนสำหรับการเลิกใช้exists()

Nodejs พร้อม build in contract (โหนด 7+)

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

กรอบจาวาสคริปต์ยอดนิยม

FS-พิเศษ

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

อย่างที่คุณเห็นง่ายกว่ามาก และข้อดีเหนือคำสัญญาคือคุณมีการพิมพ์ที่สมบูรณ์ด้วยแพคเกจนี้ (Intellisense / typescript สมบูรณ์)! กรณีส่วนใหญ่คุณจะรวมไลบรารีนี้แล้วเนื่องจาก (+ -10.000) ไลบรารีอื่น ๆ ขึ้นอยู่กับมัน


0

คุณสามารถใช้fs.statเพื่อตรวจสอบว่าเป้าหมายเป็นไฟล์หรือไดเรกทอรีและคุณสามารถใช้fs.accessเพื่อตรวจสอบว่าคุณสามารถเขียน / อ่าน / เรียกใช้ไฟล์ (จำไว้ว่าให้ใช้path.resolveเพื่อรับเส้นทางแบบเต็มสำหรับเป้าหมาย)

เอกสารอ้างอิง:

ตัวอย่างเต็มรูปแบบ (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

สำหรับเวอร์ชั่นอะซิงโครนัส! และด้วยรุ่นสัญญา! นี่เป็นวิธีที่เรียบง่ายสะอาดตา!

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

ตัวอย่างที่เป็นประโยชน์มากขึ้นจากรหัสของฉันเพื่อแสดงให้เห็นได้ดีขึ้น


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

ตัวอย่างข้างต้นเป็นเพียงการสาธิต! ฉันสามารถใช้เหตุการณ์ข้อผิดพลาดของสตรีมการอ่านได้! เพื่อตรวจจับข้อผิดพลาดใด ๆ ! และข้ามสองสาย!

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.