ตรวจสอบซิงโครไนซ์ว่ามีไฟล์ / ไดเรกทอรีอยู่ใน Node.js หรือไม่


1208

ฉันจะตรวจสอบแบบซิงโครนัสโดยใช้node.jsได้อย่างไรถ้ามีไฟล์หรือไดเรกทอรีอยู่?


58
การทำงานแบบซิงโครนัสนั้นยอดเยี่ยมสำหรับการดำเนินการกับไฟล์ / ไดเรกทอรีแบบครั้งเดียวก่อนส่งคืนโมดูล ตัวอย่างเช่นการบูตไฟล์การกำหนดค่า
jocull

1
@PaulDraper ที่มีแคชที่อบอุ่นไม่เป็นจริงในทุกกรณี
mikemaccana

12
ไม่ว่าจะเป็นการแสดงบางครั้งคุณเพียงต้องการเรียกใช้ด้วยวิธีซิงค์เพื่อประสบการณ์นักพัฒนาซอฟต์แวร์ ตัวอย่างเช่นหากคุณกำลังใช้ Node สำหรับสคริปต์การประมวลผลข้อมูลซึ่งควรออกแบบโดยการบล็อกในกรณีที่ async existsเพียงแค่เพิ่มการโทรกลับที่ไม่จำเป็น
Kunok

3
+1 แถลงการณ์ของ Kunok อย่างแน่นอน ในส่วนที่เหลือของรหัสของฉันฉันทำรหัสที่ซับซ้อนมากขึ้นเมื่อมันเป็นคอขวดที่ความเร็วสำคัญจริงๆ ทำไมฉันไม่ใช้หลักการนั้นกับการอ่านไฟล์? ในหลาย ๆ ส่วนของความเรียบง่าย / ความสามารถในการอ่านรหัสของโปรแกรมมีความสำคัญมากกว่าความเร็วในการประมวลผล หากเป็นพื้นที่คอขวดฉันจะใช้วิธี async เพื่อป้องกันไม่ให้มีการเรียกใช้โค้ดอีก มิฉะนั้น ... การซิงค์ดีเยี่ยม อย่าเกลียดการซิงค์แบบสุ่มตัวอย่าง
BryanGrezeszak

3
ได้โปรด ... ไม่ "น่าสังเกต" เพราะผู้ใช้ถามอย่างชัดเจนว่าจะทำอย่างไรพร้อมกัน
jClark

คำตอบ:


2240

คำตอบของคำถามนี้เปลี่ยนไปหลายปี ปัจจุบันคำตอบอยู่ที่นี่ที่ด้านบนตามด้วยคำตอบที่ต่าง ๆ ในช่วงปีที่ผ่านมาตามลำดับ:

คำตอบปัจจุบัน

คุณสามารถใช้fs.existsSync():

const fs = require("fs"); // Or `import fs from "fs";` with ESM
if (fs.existsSync(path)) {
    // Do something
}

มันเลิกใช้มาหลายปีแล้ว แต่ไม่มีอีกต่อไปแล้ว จากเอกสาร:

โปรดทราบว่าfs.exists()เลิกใช้แล้ว แต่fs.existsSync()ไม่ใช่ (พารามิเตอร์ callback เพื่อfs.exists()ยอมรับพารามิเตอร์ที่ไม่สอดคล้องกับการเรียกกลับ Node.js อื่น ๆfs.existsSync()ไม่ได้ใช้การเรียกกลับ)

คุณเคยถามเฉพาะสำหรับซิงโครการตรวจสอบ แต่ถ้าคุณสามารถใช้ตรงกันเช็คแทน (มักจะดีที่สุดกับ I / O), การใช้งานfs.promises.accessหากคุณใช้asyncฟังก์ชั่นหรือfs.access(ตั้งแต่existsเลิก ) หากไม่ได้:

ในasyncฟังก์ชั่น:

try {
    await fs.promises.access("somefile");
    // The check succeeded
} catch (error) {
    // The check failed
}

หรือโทรกลับด้วย:

fs.access("somefile", error => {
    if (!error) {
        // The check succeeded
    } else {
        // The check failed
    }
});

คำตอบทางประวัติศาสตร์

นี่คือคำตอบทางประวัติศาสตร์ตามลำดับเวลา:

  • คำตอบเดิมจาก 2010
    ( stat/ statSyncหรือlstat/ lstatSync)
  • อัปเดตกันยายน 2555
    ( exists/ existsSync)
  • อัปเดตกุมภาพันธ์ 2558
    (กำลังสังเกตเห็นว่ามีการคัดค้านexists/ existsSyncดังนั้นเราอาจจะกลับไปที่stat/ statSyncหรือlstat/ lstatSync)
  • อัปเดตธันวาคม 2558
    (นอกจากนี้ยังมีfs.access(path, fs.F_OK, function(){})/ fs.accessSync(path, fs.F_OK)แต่โปรดทราบว่าหากไฟล์ / ไดเรกทอรีไม่มีอยู่มันเป็นข้อผิดพลาด; เอกสารสำหรับการfs.statแนะนำให้ใช้fs.accessหากคุณต้องการตรวจสอบการมีอยู่โดยไม่เปิด)
  • อัปเดตธันวาคม 2559
    fs.exists()ยังคงเลิกใช้แล้ว แต่fs.existsSync()ไม่เลิกใช้อีกต่อไป ดังนั้นคุณสามารถใช้งานได้อย่างปลอดภัยทันที

คำตอบเดิมจาก 2010:

คุณสามารถใช้statSyncหรือlstatSync( เอกสารเชื่อมโยง ) ซึ่งให้คุณวัตถุfs.Stats โดยทั่วไปหากมีฟังก์ชั่นรุ่นซิงโครนัสก็จะมีชื่อเดียวกันกับเวอร์ชัน async Syncเมื่อสิ้นสุด ดังนั้นstatSyncเป็นรุ่นซิงโครของstat; lstatSyncเป็นเวอร์ชันซิงโครนัสของlstatฯลฯ

lstatSync บอกให้คุณทราบว่ามีบางสิ่งอยู่หรือไม่และถ้าเป็นเช่นนั้นจะเป็นไฟล์หรือไดเรกทอรี (หรือในบางระบบไฟล์ลิงก์สัญลักษณ์อุปกรณ์บล็อกอุปกรณ์อักขระ ฯลฯ ) เช่นหากคุณต้องการทราบว่ามีอยู่หรือไม่และเป็น ไดเรกทอรี:

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) {
    // ...
}

... และในทำนองเดียวกันถ้าเป็นไฟล์ที่มีisFile; ถ้ามันเป็นอุปกรณ์บล็อคมีisBlockDeviceฯลฯ ฯลฯ หมายเหตุtry/catch; มันจะพ่นข้อผิดพลาดหากไม่มีรายการเลย

หากคุณไม่สนใจสิ่งที่รายการนั้นและต้องการที่จะรู้ว่ามันมีอยู่คุณสามารถใช้path.existsSync(หรือล่าสุดfs.existsSync) ตามที่ระบุไว้โดย user618408 :

var path = require('path');
if (path.existsSync("/the/path")) { // or fs.existsSync
    // ...
}

ไม่จำเป็นต้องมีtry/catchแต่ให้ข้อมูลเกี่ยวกับสิ่งที่เป็นเพียงว่ามันมี path.existsSyncเลิกใช้มานานแล้ว


หมายเหตุด้านข้าง: คุณได้ถามวิธีการตรวจสอบแบบซิงโครนัสอย่างชัดเจนดังนั้นฉันจึงใช้xyzSyncฟังก์ชั่นเวอร์ชั่นด้านบน แต่ถ้าเป็นไปได้ด้วย I / O จะดีที่สุดในการหลีกเลี่ยงการโทรแบบซิงโครนัส การโทรเข้าระบบย่อย I / O ใช้เวลาอย่างมากจากมุมมองของ CPU โปรดทราบว่าการโทรนั้นง่ายlstatกว่าlstatSync:

// Is it a directory?
lstat('/the/path', function(err, stats) {
    if (!err && stats.isDirectory()) {
        // Yes it is
    }
});

แต่ถ้าคุณต้องการรุ่นซิงโครนัสก็มี

อัปเดตกันยายน 2555

คำตอบด้านล่างจากสองสามปีที่ผ่านมาขณะนี้ล้าสมัยไปแล้ว วิธีปัจจุบันคือการใช้fs.existsSyncเพื่อทำการตรวจสอบแบบซิงโครนัสสำหรับการมีอยู่ของไฟล์ / ไดเรกทอรี (หรือแน่นอน fs.existsสำหรับการตรวจสอบแบบอะซิงโครนัส) แทนที่จะเป็นpathรุ่นด้านล่าง

ตัวอย่าง:

var fs = require('fs');

if (fs.existsSync(path)) {
    // Do something
}

// Or

fs.exists(path, function(exists) {
    if (exists) {
        // Do something
    }
});

อัปเดตกุมภาพันธ์ 2558

และที่นี่เราอยู่ในปี 2015 และเอกสารโหนดตอนนี้บอกว่าfs.existsSync(และfs.exists) "จะถูกคัดค้าน" (เพราะคนโหนดคิดว่ามันเป็นใบ้ที่จะตรวจสอบว่ามีบางสิ่งบางอย่างอยู่ก่อนที่จะเปิดมันซึ่งมันเป็น; แต่นั่นไม่ใช่เหตุผลเดียวในการตรวจสอบว่ามีบางสิ่งบางอย่างอยู่!)

ดังนั้นเราอาจจะกลับไปใช้statวิธีการต่าง ๆ... จนกระทั่ง / จนกว่าจะมีการเปลี่ยนแปลงอีกครั้งแน่นอน

อัปเดตธันวาคม 2558

ไม่ทราบว่าระยะเวลาที่จะได้รับมี แต่ยังมี/fs.access(path, fs.F_OK, ...) fs.accessSync(path, fs.F_OK)และอย่างน้อยจนถึงเดือนตุลาคม 2559 ขอแนะนำให้ใช้fs.statเอกสารfs.accessในการตรวจสอบการมีอยู่ ( "หากต้องการตรวจสอบว่ามีไฟล์อยู่หรือไม่โดยไม่ต้องจัดการมันในภายหลังfs.access()" ) แต่โปรดทราบว่าการเข้าถึงที่ไม่พร้อมใช้งานจะถือเป็นข้อผิดพลาดดังนั้นนี่อาจเป็นวิธีที่ดีที่สุดหากคุณคาดว่าไฟล์จะสามารถเข้าถึงได้:

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

อัปเดตธันวาคม 2559

คุณสามารถใช้fs.existsSync():

if (fs.existsSync(path)) {
    // Do something
}

มันเลิกใช้มาหลายปีแล้ว แต่ไม่มีอีกต่อไปแล้ว จากเอกสาร:

โปรดทราบว่าfs.exists()เลิกใช้แล้ว แต่fs.existsSync()ไม่ใช่ (พารามิเตอร์ callback เพื่อfs.exists()ยอมรับพารามิเตอร์ที่ไม่สอดคล้องกับการเรียกกลับ Node.js อื่น ๆfs.existsSync()ไม่ได้ใช้การเรียกกลับ)


7
path.exists และ path.existsSync ทั้งคู่ถูกคัดค้าน fs.exists และ fs.existsSync
ดึง

15
"โหนดคนคิดว่ามันเป็นใบ้ที่จะตรวจสอบว่ามีบางสิ่งบางอย่างอยู่ก่อนที่จะเปิดมันซึ่งมันเป็น;" เหตุใดจึงเป็นใบ้ที่จะตรวจสอบว่ามีไฟล์อยู่หรือไม่
Petr Hurtak

32
@PetrHurtak: มันไม่ได้เสมอ (เพราะมีเหตุผลมากมายสำหรับการตรวจสอบว่ามีอยู่) แต่ถ้าคุณกำลังจะเปิดไฟล์มันจะดีที่สุดที่จะแค่openโทรออกและจัดการกับข้อยกเว้นหรืออะไรก็ตามถ้าไฟล์ไม่ได้ พบ ท้ายที่สุดแล้วโลกแห่งความเป็นจริงนั้นวุ่นวาย: ถ้าคุณตรวจสอบก่อนและอยู่ที่นั่นนั่นไม่ได้หมายความว่ามันจะยังคงอยู่ที่นั่นเมื่อคุณพยายามเปิดมัน หากคุณตรวจสอบก่อนและไม่มีอยู่นั่นไม่ได้หมายความว่าจะไม่เกิดขึ้นอีกในภายหลัง สิ่งที่กำหนดเวลาเช่นนั้นดูเหมือนกรณีขอบ แต่พวกเขาขึ้นมาตลอดเวลา ดังนั้นหากคุณกำลังจะเปิดไม่มีจุดในการตรวจสอบก่อน
TJ Crowder

13
และที่นี่ฉันคิดว่ามันเป็นรูปแบบการต่อต้านที่จะใช้ข้อผิดพลาดสำหรับโฟลว์การควบคุม: ลิงก์
argyle

4

124

มองไปที่แหล่งที่มามีรุ่นซิงโคร-path.exists path.existsSyncดูเหมือนว่าจะพลาดในเอกสาร

ปรับปรุง:

path.existsและpath.existsSyncตอนนี้เลิกใช้ โปรดใช้fs.existsfs.existsSyncและ

อัปเดตปี 2559:

fs.exists และfs.existsSyncยังได้ รับการคัดค้าน ใช้fs.stat ()หรือfs.access ()แทน

อัปเดต 2019:

fs.existsSyncใช้ มันไม่ได้เลิก https://nodejs.org/api/fs.html#fs_fs_existssync_path


1
path.existsSync (p) อยู่ใน 0.4.10 docs nodejs.org/docs/v0.4.10/api/path.html
Paul Beusterien

21
ที่จริงแล้วคำตอบล่าสุด: path.existsSync นั้นเลิกใช้แล้ว fs.existsSyncมันถูกเรียกว่าตอนนี้
Olivier Lalonde

9
ตอนนี้เอกสารกำลังบอกว่า fs.exists จะถูกคัดค้าน nodejs.org/api/fs.html#fs_fs_existssync_path
Greg Hornby

ฉันเขียนห้องสมุดเล็ก ๆ เพื่อแทนที่existsฟังก์ชั่นเก่า:is-there
IonicăBizău

6
เอกสาร currenct (รุ่น ~ 9) ระบุfs.existsว่าเลิกใช้แล้วในขณะที่fs.existsSyncไม่ใช่!
Kunok

57

การใช้ API ที่แนะนำในปัจจุบัน (ณ ปี 2015) (ต่อ Node docs) นี่คือสิ่งที่ฉันทำ:

var fs = require('fs');

function fileExists(filePath)
{
    try
    {
        return fs.statSync(filePath).isFile();
    }
    catch (err)
    {
        return false;
    }
}

เพื่อตอบสนองต่อปัญหา EPERM ที่ @broadband ให้ไว้ในความคิดเห็นซึ่งนำมาซึ่งจุดที่ดี fileExists () อาจไม่ใช่วิธีที่ดีที่จะคิดเกี่ยวกับเรื่องนี้ในหลาย ๆ กรณีเพราะ fileExists () ไม่สามารถรับประกันการส่งคืนบูลีนได้ คุณอาจสามารถกำหนดได้อย่างชัดเจนว่าไฟล์นั้นมีอยู่หรือไม่มีอยู่ แต่คุณอาจได้รับข้อผิดพลาดในการอนุญาต ข้อผิดพลาดของการอนุญาตไม่ได้หมายความว่าไฟล์นั้นมีอยู่เพราะคุณอาจไม่ได้รับอนุญาตไปยังไดเรกทอรีที่มีไฟล์ที่คุณกำลังตรวจสอบอยู่ และแน่นอนว่ามีโอกาสที่คุณจะพบข้อผิดพลาดอื่น ๆ ในการตรวจสอบการมีอยู่ของไฟล์

ดังนั้นรหัสของฉันข้างต้นคือ doesFileExistAndDoIHaveAccessToIt () แต่คำถามของคุณอาจจะเป็นแบบ FileNotExistAndCouldICreateIt () ซึ่งจะเป็นตรรกะที่แตกต่างอย่างสิ้นเชิง

ในขณะที่คำตอบ fs.existsSync ตอบคำถามที่ถามที่นี่โดยตรงซึ่งมักจะไม่ใช่สิ่งที่คุณต้องการ (คุณไม่เพียงแค่ต้องการรู้ว่ามีบางสิ่งที่มีอยู่ในเส้นทางหรือไม่คุณอาจสนใจว่าสิ่งนั้นเป็นอะไร ที่มีอยู่คือไฟล์หรือไดเรกทอรี)

บรรทัดล่างคือว่าถ้าคุณกำลังตรวจสอบเพื่อดูว่าไฟล์ที่มีอยู่คุณอาจทำเช่นนั้นเพราะคุณตั้งใจที่จะดำเนินการบางอย่างขึ้นอยู่กับผลและตรรกะนั้น (การตรวจสอบและ / หรือการกระทำที่ตามมา) ควรรองรับความคิด สิ่งที่พบในเส้นทางนั้นอาจเป็นไฟล์หรือไดเรกทอรีและคุณอาจพบ EPERM หรือข้อผิดพลาดอื่น ๆ ในกระบวนการตรวจสอบ


4
ดีฉันเพิ่ม || isDirectory () เพื่อให้เป็นตัวตรวจสอบไฟล์ / โฟลเดอร์ var stats = fs.statSync (filePath); return stats.isFile () || stats.isDirectory ();
บ๊อบ

4
หากโปรแกรมไม่มีสิทธิ์ในการเข้าถึงไฟล์โปรแกรมจะยังคงส่งคืนค่าเท็จแม้ว่าไฟล์นั้นจะมีอยู่นั่นคือลบไฟล์ทั้งหมดออกจากไฟล์ chmod ugo-rwx file.txt หรือใน Windows คลิกขวา ... ข้อความข้อยกเว้น: ข้อยกเว้น fs.statSync (./ f.txt): ข้อผิดพลาด: EPERM: ไม่อนุญาตให้ดำเนินการ, สถิติ 'X: \ f.txt' ดังนั้นกรณีนี้ไม่ครอบคลุมโดยรหัสบน
บรอดแบนด์

2
ว้าวบางครั้ง JS ก็ปัญญาอ่อน แน่นอนว่า 97% ของเวลาที่คุณจะใช้ไฟล์ แต่ไม่มีประโยชน์ง่ายๆfile.exists()สำหรับ 3% และบังคับให้เราห่อสิ่งเหล่านี้ด้วยการลองเล่นแทน? รับจริง ... Bitch ประจำวันนี้
expelledboy

20

การปรับปรุงอื่น

ต้องการคำตอบสำหรับคำถามนี้ด้วยตัวเองฉันค้นหาโหนดเอกสารดูเหมือนว่าคุณไม่ควรใช้ fs.exists แทนใช้ fs.open และใช้ข้อผิดพลาดเอาต์พุตเพื่อตรวจสอบว่าไม่มีไฟล์อยู่หรือไม่:

จากเอกสาร:

fs.exists () เป็นความผิดสมัยและมีอยู่เพื่อเหตุผลทางประวัติศาสตร์เท่านั้น ไม่ควรมีเหตุผลที่จะใช้มันในรหัสของคุณเอง

โดยเฉพาะอย่างยิ่งการตรวจสอบว่ามีไฟล์อยู่ก่อนเปิดเป็นรูปแบบการต่อต้านที่ทำให้คุณเสี่ยงต่อสภาวะการแข่งขันหรือไม่: กระบวนการอื่นอาจลบไฟล์ระหว่างการเรียกไปยัง fs.exists () และ fs.open () เพียงเปิดไฟล์และจัดการข้อผิดพลาดเมื่อไม่มี

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


1
มีวิธีที่จะทำกับ openSync แทนที่จะเปิด
Greg Hornby

1
@ GregHorn โดยฉันคิดว่ามันควรจะทำงานในลักษณะเดียวกันกับ openSync
Melbourne2991

2
สำหรับผู้ที่ยังคงต้องexists และฉันสร้างexistsSync is-there
IonicăBizău

6
การคัดค้านครั้งนี้ทำให้ฉันคลั่ง การเปิดไฟล์เพื่อดูว่ามีข้อผิดพลาดเกิดขึ้นหรือไม่ดูเหมือนเป็นการสิ้นเปลืองทรัพยากรเมื่อจำเป็นทั้งหมดคือความรู้เกี่ยวกับการมีอยู่ของไฟล์
Josh Hansen

11

ฉันใช้ฟังก์ชันด้านล่างเพื่อทดสอบว่ามีไฟล์อยู่หรือไม่ มันจับข้อยกเว้นอื่น ๆ ดังนั้นในกรณีที่มีปัญหาสิทธิ์เช่นchmod ugo-rwx filenameหรือในRight Click -> Properties -> Security -> Advanced -> Permission entries: empty list ..ฟังก์ชันWindows ส่งคืนข้อยกเว้นตามที่ควร มีไฟล์อยู่ แต่เราไม่มีสิทธิ์ในการเข้าถึง มันจะผิดที่จะละเว้นข้อยกเว้นประเภทนี้

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

เอาต์พุตข้อยกเว้นเอกสารคู่มือข้อผิดพลาด nodejsในไฟล์ case ไม่มีอยู่:

{
  [Error: ENOENT: no such file or directory, stat 'X:\\delsdfsdf.txt']
  errno: -4058,
  code: 'ENOENT',
  syscall: 'stat',
  path: 'X:\\delsdfsdf.txt'
}

ข้อยกเว้นในกรณีที่เราไม่มีสิทธิ์ในไฟล์ แต่มีอยู่:

{
  [Error: EPERM: operation not permitted, stat 'X:\file.txt']
  errno: -4048,
  code: 'EPERM',
  syscall: 'stat',
  path: 'X:\\file.txt'
}

2
อย่างนี้มันเป็นหนึ่งในไม่กี่คำตอบที่ทันสมัยตั้งแต่โหนดได้คัดค้าน 37 วิธีสุดท้ายในการทำเช่นนี้
1mike12

คุณช่วยฉันหน่อย ฉันสามารถประหยัดเวลาได้ถ้าฉันได้อ่านสิ่งนี้
jgmjgm

5

fs.exists () เลิกใช้แล้วอย่าใช้ https://nodejs.org/api/fs.html#fs_fs_exists_path_callback

คุณสามารถใช้วิธี core nodejs ที่ใช้ในสิ่งนี้: 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;
}

สิ่งนี้จะส่งคืนออบเจกต์สถิติจากนั้นเมื่อคุณได้รับออบเจกต์สถิติที่คุณสามารถลองได้

var exist = statPath('/path/to/your/file.js');
if(exist && exist.isFile()) {
  // do something
}

4

บางคำตอบที่นี่บอกว่าfs.existsและfs.existsSyncเลิกทั้งคู่ ตามเอกสารนี้ไม่เป็นความจริงอีกต่อไป fs.existsตอนนี้จะถูกตัดออกเท่านั้น:

โปรดทราบว่า fs.exists () เลิกใช้แล้ว แต่ fs.existsSync () ไม่ใช่ (พารามิเตอร์ callback สำหรับ fs.exists () ยอมรับพารามิเตอร์ที่ไม่สอดคล้องกับ Node.js callbacks อื่น ๆ fs.existsSync () ไม่ใช้การเรียกกลับ)

ดังนั้นคุณสามารถใช้fs.existsSync ()เพื่อตรวจสอบไฟล์พร้อมกันได้หรือไม่


3

pathโมดูลไม่ให้รุ่นซิงโครpath.existsเพื่อให้คุณมีที่จะหลอกลวงรอบกับfsโมดูล

สิ่งที่เร็วที่สุดที่ฉันสามารถจินตนาการได้คือการใช้fs.realpathSyncซึ่งจะทำให้เกิดข้อผิดพลาดที่คุณต้องจับดังนั้นคุณต้องสร้างฟังก์ชั่นเสื้อคลุมของคุณเองด้วยการลอง / จับ


1

การใช้การทดสอบ fileSystem (fs) จะทำให้เกิดข้อผิดพลาดของวัตถุซึ่งคุณจะต้องทำการตัดคำสั่ง try / catch ช่วยตัวเองบ้างและใช้ฟีเจอร์แนะนำในสาขา 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 อยู่ภายใต้ fs ดังนั้นจึงเป็น fs.exists (เส้นทาง, การเรียกกลับ)
ทอดด์ Moses

0

เอกสารที่fs.stat()ระบุว่าจะใช้fs.access()หากคุณไม่ต้องการจัดการไฟล์ มันไม่ได้ให้เหตุผลอาจจะเร็วกว่าหรือน้อยกว่าการใช้ memeory?

ฉันใช้โหนดสำหรับการทำงานอัตโนมัติเชิงเส้นดังนั้นฉันคิดว่าฉันแบ่งปันฟังก์ชั่นที่ฉันใช้เพื่อทดสอบการมีอยู่ของไฟล์

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

อัปเดต asnwer สำหรับคนเหล่านั้นอย่างถูกต้องชี้ให้เห็นว่ามันไม่ได้ตอบคำถามโดยตรงนำตัวเลือกเพิ่มเติม

โซลูชันการซิงค์:

fs.existsSync('filePath')นอกจากนี้ยังเห็นเอกสารที่นี่

ผลตอบแทนจริงถ้าเส้นทางที่มีอยู่เป็นเท็จอย่างอื่น

โซลูชัน Async Promise

ในบริบท async คุณสามารถเขียนเวอร์ชัน async ในวิธีการซิงค์ด้วยการใช้awaitคำหลัก คุณสามารถเปลี่ยนวิธีการโทรกลับ async ให้เป็นสัญญาเช่นนี้:

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

เอกสารที่เกี่ยวกับการเข้าถึง ()


1
OP ต้องการโซลูชันแบบซิงโครนัส
vdegenne

คุณควรอัปเดตรหัสของคุณเป็น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); }, ); }); }
pery mimon

0

โอกาสที่ถ้าคุณต้องการทราบว่ามีไฟล์อยู่หรือไม่คุณวางแผนที่จะใช้มันหากมี

function getFile(path){
    try{
        return require(path);
    }catch(e){
        return false;
    }
}

-1

นี่คือวิธีแก้ปัญหา wrapper ง่าย ๆ สำหรับสิ่งนี้:

var fs = require('fs')
function getFileRealPath(s){
    try {return fs.realpathSync(s);} catch(e){return false;}
}

การใช้งาน:

  • ทำงานได้ทั้งไดเรกทอรีและไฟล์
  • หากมีรายการอยู่ก็จะส่งคืนพา ธ ไปยังไฟล์หรือไดเรกทอรี
  • ถ้าไม่มีรายการมันจะคืนค่าเท็จ

ตัวอย่าง:

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

ตรวจสอบให้แน่ใจว่าคุณใช้ตัวดำเนินการ === เพื่อทดสอบว่าผลตอบแทนเท่ากับเท็จ ไม่มีเหตุผลเชิงตรรกะที่ fs.realpathSync () จะคืนค่าเท็จภายใต้สภาพการทำงานที่เหมาะสมดังนั้นฉันคิดว่าสิ่งนี้ควรจะทำงานได้ 100%

ฉันต้องการดูวิธีแก้ปัญหาที่ไม่ได้สร้างข้อผิดพลาดและประสิทธิภาพการทำงานที่ได้รับผลกระทบ จากมุมมองของ API fs.exists () ดูเหมือนจะเป็นทางออกที่ดีที่สุด


1
@ แดนขอบคุณ ฉันลบข้อความที่ถูกตัดทอน ฉันจำไม่ได้ว่าบันทึกนั้นคืออะไร ถ้ามันมาถึงฉันฉันจะเพิ่มบันทึก
ทิโมธีซีควินน์

1
Np ฉันกำลังลบความคิดเห็นของฉัน
Dan Dascalescu

-2

จากคำตอบปรากฏว่าไม่มีการสนับสนุน API อย่างเป็นทางการสำหรับเรื่องนี้ (ในการตรวจสอบโดยตรงและชัดเจน) คำตอบหลายคำบอกว่าจะใช้สถิติอย่างไรก็ตามพวกเขาไม่เข้มงวด เราไม่สามารถสันนิษฐานได้ว่ามีข้อผิดพลาดใด ๆ เกิดขึ้นจากสถิติหมายความว่าไม่มีอะไรเกิดขึ้น

ให้บอกว่าเราลองกับสิ่งที่ไม่มีอยู่:

$ 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' }

ลองด้วยสิ่งที่มีอยู่ แต่เราไม่สามารถเข้าถึง:

$ 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' }

อย่างน้อยที่สุดคุณจะต้อง:

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

คำถามไม่ชัดเจนหากคุณต้องการให้เป็นแบบซิงโครนัสหรือถ้าคุณเพียงต้องการให้เขียนราวกับว่าเป็นแบบซิงโครนัส ตัวอย่างนี้ใช้ await / async เพื่อให้เขียนเป็นแบบซิงโครนัสเท่านั้น แต่ทำงานแบบอะซิงโครนัส

ซึ่งหมายความว่าคุณต้องโทรหาเช่นนี้ที่ระดับบนสุด:

(async () => {
    try {
        console.log(await dir_exists('god'));
        console.log(await dir_exists('fsm/appendage'));
    }
    catch(e) {
        console.log(e);
    }
})();

อีกทางเลือกหนึ่งคือใช้. แล้วและ. จับสัญญาที่ส่งคืนจากการโทร async หากคุณต้องการมันเพิ่มเติม

หากคุณต้องการตรวจสอบว่ามีบางสิ่งอยู่หรือไม่คุณควรตรวจสอบให้แน่ใจว่าเป็นประเภทที่ถูกต้องเช่นไดเรกทอรีหรือไฟล์ สิ่งนี้รวมอยู่ในตัวอย่าง หากไม่ได้รับอนุญาตให้เป็น symlink คุณต้องใช้ lstat แทน stat เนื่องจาก stat จะทำการสำรวจลิงก์โดยอัตโนมัติ

คุณสามารถแทนที่ async ทั้งหมดเพื่อซิงค์รหัสที่นี่และใช้ statSync แทน อย่างไรก็ตามคาดว่าเมื่อ async และรอคอยเป็นสากลรองรับการโทร Sync จะกลายเป็นซ้ำซ้อนในที่สุดจะถูกคิดค่าเสื่อมราคา


1
คำถามเดิมไม่ได้ระบุว่า ฉันยังแสดงให้เห็นถึงวิธีการทำสิ่งต่าง ๆ อย่างไม่น่าสงสัย คำตอบมากมายอาจทำให้เกิดบั๊กเนื่องจากขาดความชัดเจน ผู้คนมักต้องการโปรแกรมสิ่งต่าง ๆ ดังนั้นจึงดูเหมือนว่าเป็นแบบซิงโครนัส แต่ไม่จำเป็นต้องมีการดำเนินการแบบซิงโครนัส statSync ไม่เหมือนกับรหัสที่ฉันแสดง บัญชีของสิ่งที่ต้องการจริง ๆ นั้นไม่ชัดเจนดังนั้นคุณจะต้องใช้การตีความส่วนบุคคลของคุณเท่านั้น หากคุณพบคำตอบที่คุณไม่เข้าใจอาจเป็นการดีกว่าที่จะขอความคิดเห็นหรือ PM เพื่อแก้ไขสิ่งที่จำเป็นต้องใช้
jgmjgm

1
หากคุณต้องการคุณยังสามารถขโมยตัวอย่างรหัสของฉันตั้งชื่ออย่างเหมาะสมวางไว้บน github เพิ่มลงใน npm จากนั้นคำตอบจะเป็นหนึ่งบรรทัด / ลิงค์: D
jgmjgm

รหัสย่อมาจากตัวอย่าง แต่คุณสามารถส่งคำแนะนำแก้ไขเพื่อรวม &&! isFile หรือตรวจสอบ symlink ฯลฯ (อีกครั้งแม้ว่าคำถามจะไม่ระบุอย่างชัดเจนแม้เป็นสิ่งที่พวกเขาต้องการ) เมื่อฉันได้ชี้ให้เห็นแล้วว่าคำตอบของฉันเป็นไปตามการตีความคำถามหนึ่งข้อและไม่ได้ทำในสิ่งเดียวกันกับที่คุณเสนอในบรรทัดเดียว
jgmjgm
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.