Як я можу синхронно перевірити, використовуючи node.js , чи існує файл чи каталог?
exists
просто додає непотрібні зворотні виклики.
Як я можу синхронно перевірити, використовуючи node.js , чи існує файл чи каталог?
exists
просто додає непотрібні зворотні виклики.
Відповіді:
Відповідь на це питання роками змінювався. Поточний відповідь тут у верхній частині, а потім різними відповідями на протязі багатьох років в хронологічному порядку:
Ви можете використовувати fs.existsSync()
:
const fs = require("fs"); // Or `import fs from "fs";` with ESM
if (fs.existsSync(path)) {
// Do something
}
Він був застарілий протягом декількох років, але більше не є. З документів:
Зауважте, що
fs.exists()
застаріле, алеfs.existsSync()
це не так. (Параметр зворотного викликуfs.exists()
приймає параметри, несумісні з іншими зворотніми викликами Node.js.fs.existsSync()
Не використовує зворотного дзвінка.)
Ви спеціально просили синхронну перевірку, але якщо ви можете замість цього використовувати асинхронну перевірку (як правило, найкраще з введенням-виведенням), використовуйте, 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
}
});
Ось історичні відповіді в хронологічному порядку:
stat
/ statSync
або lstat
/ lstatSync
)exists
/ existsSync
)exists
/ existsSync
, тому ми, ймовірно, повертаємось до stat
/ statSync
або lstat
/ lstatSync
)fs.access(path, fs.F_OK, function(){})
/ fs.accessSync(path, fs.F_OK)
, але зауважте, що якщо файл / каталог не існує, це помилка; документи fs.stat
рекомендують використовувати, fs.access
якщо вам потрібно перевірити наявність без відкриття)fs.exists()
все ще застаріло, але fs.existsSync()
більше не застаріло. Тому ви можете сміливо використовувати його зараз.Ви можете використовувати statSync
або lstatSync
( посилання на документи ), що дає вам fs.Stats
об’єкт . Загалом, якщо доступна синхронна версія функції, вона буде мати те саме ім’я, що і версія асинхронізації 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
), як зазначив користувач618408 :
var path = require('path');
if (path.existsSync("/the/path")) { // or fs.existsSync
// ...
}
Це не вимагає, try/catch
але не дає вам інформації про те, в чому річ, тільки що вона там є. path.existsSync
була давно застаріла.
Бічна примітка: Ви прямо запитували, як перевірити синхронно , тому я використовував xyzSync
версії функцій, наведених вище. Але де це можливо, з вводу-виводу, насправді найкраще уникати синхронних дзвінків. Дзвінки в підсистему вводу / виводу потребують значного часу з точки зору процесора. Зауважте, як легко телефонувати, lstat
а не lstatSync
:
// Is it a directory?
lstat('/the/path', function(err, stats) {
if (!err && stats.isDirectory()) {
// Yes it is
}
});
Але якщо вам потрібна синхронна версія, вона є.
Нижченаведена відповідь, яка була пару років тому, тепер трохи застаріла. Поточний спосіб полягає у використанні 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
}
});
І ось ми у 2015 році, і документи Node тепер кажуть, що fs.existsSync
(і fs.exists
) "буде застарілим". (Тому що люди з Вузла думають, що німе, щоб перевірити, чи щось існує, перш ніж відкрити, що це таке; але це не єдина причина перевірки, чи щось існує!)
Тож ми, мабуть, повертаємось до різних stat
методів ... До /, якщо це ще раз не зміниться, звичайно.
Не знаю, як довго це було, але є також fs.access(path, fs.F_OK, ...)
/fs.accessSync(path, fs.F_OK)
. І принаймні станом на жовтень 2016 року в 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
}
});
Ви можете використовувати fs.existsSync()
:
if (fs.existsSync(path)) {
// Do something
}
Він був застарілий протягом декількох років, але більше не є. З документів:
Зауважте, що
fs.exists()
застаріле, алеfs.existsSync()
це не так. (Параметр зворотного викликуfs.exists()
приймає параметри, несумісні з іншими зворотніми викликами Node.js.fs.existsSync()
Не використовує зворотного дзвінка.)
open
виклик і обробити виняток або все, якщо файл не був знайдено. Зрештою, реальний світ хаотичний: якщо ви спочатку перевірите, чи він там, це не означає, що він все одно буде там, коли ви намагаєтесь його відкрити; якщо ви перевірите спочатку, а його там немає, це не означає, що мить його не буде. Зубчасте тощо , здається , як крайні випадки, але вони приходять все час . Тож якщо ви збираєтеся відкривати, немає сенсу перевіряти спочатку.
Дивлячись на джерело, є синхронна версія path.exists
- path.existsSync
. Схоже, його пропустили в документах.
path.exists
і path.existsSync
тепер застарілі . Будь ласка, використовуйте .fs.exists
таfs.existsSync
fs.exists
а були застарілими . Використовуйте натомість fs.stat () або fs.access () .fs.existsSync
також
використання fs.existsSync
. Це не застаріло.
https://nodejs.org/api/fs.html#fs_fs_existssync_path
fs.existsSync
.
exists
функцію:is-there
fs.exists
як застарілі, поки fs.existsSync
немає!
Використовуючи рекомендовані на даний момент API (станом на 2015 рік) API (за документами Node), це я роблю:
var fs = require('fs');
function fileExists(filePath)
{
try
{
return fs.statSync(filePath).isFile();
}
catch (err)
{
return false;
}
}
У відповідь на питання EPERM, порушене @broadband у коментарях, це спричинило хороший момент. fileExists (), мабуть, не є гарним способом думати про це у багатьох випадках, тому що fileExists () насправді не може обіцяти булевого повернення. Можливо, ви зможете остаточно визначити, що файл існує чи не існує, але ви також можете отримати помилку дозволів. Помилка дозволів не обов'язково означає, що файл існує, тому що вам може не вистачити дозволу до каталогу, що містить файл, у якому ви перевіряєте. І звичайно, є ймовірність, що ви можете зіткнутися з іншою помилкою при перевірці наявності файлу.
Отже, мій код вище дійсно є FileExistAndDoIHaveAccessToIt (), але ваше запитання може бутиFileNotExistAndCouldICreateIt (), що було б зовсім іншою логікою (для цього потрібно було б пояснити помилку EPERM).
Хоча відповідь fs.existsSync стосується прямо заданого тут питання, це часто не буде таким, яким ви хочете (ви не просто хочете знати, чи існує щось на шляху, ви, мабуть, хвилюєтесь, чи є "річ" який існує - це файл або каталог).
Суть полягає в тому, що якщо ви перевіряєте, чи існує файл, ви, ймовірно, робите це, тому що ви маєте намір здійснити певні дії на основі результату, і ця логіка (перевірка та / або наступна дія) повинна відповідати ідеї що предмет, знайдений на цьому шляху, може бути файлом або каталогом, і що ви можете зіткнутися з EPERM або іншими помилками в процесі перевірки.
file.exists()
утиліти для 3%, а натомість змушуєте нас обернути це у спробі ловити? Отримайте справжню ... Сука дня.
Ще одне оновлення
Потрібно відповісти на це питання сам, я шукав документи вузла, схоже, ви не повинні використовувати fs.exists, натомість використовуйте fs.open і використовуйте виведену помилку для виявлення, якщо файл не існує:
з документів:
fs.exists () є анахронізмом і існує лише з історичних причин. Майже ніколи не повинно бути причин використовувати його у власному коді.
Зокрема, перевірка наявності файлу перед відкриттям - це антидіаграма, яка залишає вас вразливими до перегонових умов: інший процес може видалити файл між викликами до fs.exists () та fs.open (). Просто відкрийте файл і обробіть помилку, коли його немає.
Я використовую функцію нижче, щоб перевірити, чи існує файл. Це ловить і інші винятки. Тож у випадку виникнення проблем із правами, наприклад, 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 у файлі справи не існує:
{
[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'
}
fs.exists () застаріле, не використовуйте його https://nodejs.org/api/fs.html#fs_fs_exists_path_callback
Ви можете реалізувати основний спосіб 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
}
Деякі відповіді тут говорять про це fs.exists
і fs.existsSync
обидва застарілі. Згідно з документами, це більше не відповідає дійсності. Тільки fs.exists
в deprected Зараз:
Зауважте, що fs.exists () застаріле, але fs.existsSync () - ні. (Параметр зворотного виклику до fs.exists () приймає параметри, несумісні з іншими зворотними викликами Node.js. Fs.existsSync () не використовує зворотний виклик.)
Таким чином, ви можете сміливо використовувати fs.existsSync () для синхронної перевірки наявності файлу.
path
Модуль не забезпечує синхронну версію , path.exists
так що ви повинні обдурити навколо зfs
модулем.
Найшвидше, що я можу собі уявити, - це використання, fs.realpathSync
яке призведе до помилки, яку вам доведеться зловити, тому вам потрібно зробити власну функцію обгортки за допомогою спробувати.
Використання тестів fileSystem (fs) призведе до появи об'єктів помилок, які вам потім потрібно буде загорнути у операцію спробувати. Економте собі певні зусилля та скористайтеся функцією введення у відділенні 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);
});
});
Документи fs.stat()
наказує використовувати, fs.access()
якщо ви не збираєтесь маніпулювати файлом. Це не дало обґрунтування, може бути швидше чи менш спогадне використання?
Я використовую вузол для лінійної автоматизації, тому я подумав, що я поділяю функцію, яку використовую для тестування на існування файлів.
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;
}
оновлене повідомлення для тих людей, "правильно", вказуючи, що це не відповідає безпосередньо на питання, більше приносить альтернативний варіант.
fs.existsSync('filePath')
також дивіться документи тут .
Повертає істину, якщо шлях існує, інакше помилково.
У контексті асинхронізації ви можете просто записати версію 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');
}
}
документи на доступ ().
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); }, ); }); }
Швидше за все, якщо ви хочете знати, чи існує файл, ви плануєте вимагати його, якщо він є.
function getFile(path){
try{
return require(path);
}catch(e){
return false;
}
}
Ось просте рішення для цього обгортки:
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 () видається найелегантнішим рішенням.
З відповідей видно, що офіційної підтримки API для цього немає (як у прямому та явному перевірці). У багатьох відповідях йдеться про використання stat, однак вони не суворі. Ми не можемо припустити, наприклад, що будь-яка помилка, викинута статистикою, означає, що щось не існує.
Скажемо, ми спробуємо це з тим, що не існує:
$ 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);
}
})();
Альтернативою є використання .then і .catch на обіцянку, повернуту з виклику async, якщо вам це потрібно далі.
Якщо ви хочете перевірити, чи щось існує, то це добра практика, щоб також переконатися, що це правильний тип речей, таких як каталог або файл. Це включено в приклад. Якщо заборонено бути символьним посиланням, ви повинні використовувати lstat замість stat, оскільки stat автоматично переходитиме посиланнями.
Ви можете замінити тут усі асинхронізації для синхронізації коду та замість цього використовувати statSync. Однак очікуйте, що після того, як асинхронізація та очікування стануть загальнодоступними, виклики синхронізації з часом стануть надмірними, щоб знецінитися (інакше вам доведеться визначати їх скрізь і вгору по ланцюгу, як і при async, роблячи це справді безглуздо).