Как я могу синхронно проверить, используя 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) «будет объявлено устаревшим». (Потому что люди из Node думают, что глупо проверять, существует ли что-то, прежде чем открывать это, что есть; но это не единственная причина для проверки, существует ли что-то!)
Поэтому мы, вероятно, вернулись к различным 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нет!
Используя рекомендуемые в настоящее время (по состоянию на 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 (), но ваш вопрос может быть связан с doFileNotExistAndCouldICreateIt (), который будет представлять собой совершенно другую логику (которая должна учитывать ошибку EPERM, помимо прочего).
В то время как ответ fs.existsSync непосредственно отвечает на вопрос, заданный здесь, часто это не то, что вы хотите (вы не просто хотите знать, существует ли «что-то» на пути, вам, вероятно, важно знать, есть ли «вещь»). существует файл или каталог).
Суть в том, что если вы проверяете, существует ли файл, вы, вероятно, делаете это, потому что намереваетесь предпринять какое-то действие в зависимости от результата, и эта логика (проверка и / или последующее действие) должна соответствовать идее. что вещь, найденная по этому пути, может быть файлом или каталогом, и что вы можете столкнуться с EPERM или другими ошибками в процессе проверки.
file.exists()утилиты для 3%, и вместо этого вынудите нас обернуть это в попытку? Стань настоящим ... Сука дня.
Другое обновление
Нуждаясь в ответе на этот вопрос сам, я посмотрел документацию по узлу, кажется, вам не следует использовать fs.exists, вместо этого используйте fs.open и используйте выведенную ошибку, чтобы определить, не существует ли файл:
из документов:
fs.exists () является анахронизмом и существует только по историческим причинам. Почти никогда не должно быть причин использовать его в своем собственном коде.
В частности, проверка, существует ли файл перед открытием, является антишаблоном, который делает вас уязвимым для условий гонки: другой процесс может удалить файл между вызовами fs.exists () и fs.open (). Просто откройте файл и обработайте ошибку, когда ее там нет.
Я использую функцию ниже, чтобы проверить, существует ли файл. Ловит и другие исключения. Так что в случае проблем с правами, например, chmod ugo-rwx filenameили в Windows
Right Click -> Properties -> Security -> Advanced -> Permission entries: empty list ..функция возвращает исключение, как и должно быть. Файл существует, но у нас нет прав на доступ к нему. Было бы неправильно игнорировать подобные исключения.
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сейчас вычеркнуто:
Обратите внимание, что fs.exists () устарела, а fs.existsSync () - нет. (Параметр обратного вызова для fs.exists () принимает параметры, которые несовместимы с другими обратными вызовами Node.js. Fs.existsSync () не использует обратный вызов.)
Таким образом, вы можете безопасно использовать fs.existsSync (), чтобы синхронно проверить, существует ли файл.
pathМодуль не обеспечивает синхронную версию , path.existsтак что вы должны обмануть вокруг с fsмодулем.
Самая быстрая вещь, которую я могу себе представить, это использование, fs.realpathSyncкоторое выдаст ошибку, которую вы должны отловить, поэтому вам нужно создать свою собственную функцию-обертку с помощью try / catch.
Использование тестов 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);
});
});
Документы на 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;
}
обновленный asnwer для тех людей, «правильно» указывающих на то, что он не дает прямого ответа на вопрос, больше предлагает альтернативный вариант.
fs.existsSync('filePath')также см. документы здесь .
Возвращает true, если путь существует, иначе false.
В асинхронном контексте вы можете просто написать асинхронную версию в методе синхронизации с использованием awaitключевого слова. Вы можете просто превратить асинхронный метод обратного вызова в обещание, подобное этому:
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);
}
Убедитесь, что вы используете оператор ===, чтобы проверить, равен ли return false. Нет логической причины, по которой fs.realpathSync () вернул бы false при надлежащих рабочих условиях, поэтому я думаю, что это должно работать на 100%.
Я бы предпочел увидеть решение, которое не генерирует ошибку и приводит к снижению производительности. С точки зрения API fs.exists () кажется наиболее элегантным решением.
Из ответов видно, что для этого нет официальной поддержки API (как при прямой и явной проверке). Многие из ответов говорят использовать stat, однако они не являются строгими. Мы не можем предположить, например, что любая ошибка, выдаваемая 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 для обещания, возвращенного из асинхронного вызова, если вам это нужно дальше.
Если вы хотите проверить, существует ли что-то, рекомендуется также убедиться, что это правильный тип вещи, такой как каталог или файл. Это включено в пример. Если не разрешено быть символической ссылкой, вы должны использовать lstat вместо stat, так как stat будет автоматически проходить по ссылкам.
Вы можете заменить всю асинхронность для синхронизации кода здесь и использовать вместо этого statSync. Однако следует ожидать, что как только асинхронность и ожидание станут повсеместно поддерживаемыми, вызовы Sync со временем станут избыточными и будут обесцениваться (в противном случае вам придется определять их везде и по цепочке, как в случае асинхронизации, что делает его действительно бессмысленным).