Как я могу синхронно проверить, используя 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 со временем станут избыточными и будут обесцениваться (в противном случае вам придется определять их везде и по цепочке, как в случае асинхронизации, что делает его действительно бессмысленным).