Как проверить, существует ли файл или директория в PHP

Раздел: Файловая система -> Проверка файлов

Основные подходы к проверке существования в файловой системе

Наиболее универсальное и часто используемое решение - функция file_exists(). Она возвращает true, если файл или директория существуют. Однако из-за кэширования результатов предыдущих вызовов рекомендуется перед проверкой сбрасывать кэш с помощью clearstatcache().


<?php
$filename = '/var/www/data/config.php';
clearstatcache(true, $filename);
if (file_exists($filename)) {
    echo 'Файл или директория существует';
} else {
    echo 'Объект не найден';
}
?>
  

Основное преимущество - простота и работа как с файлами, так и с директориями. Недостаток: результат может устареть, если за время между проверкой и использованием объект был удалён.

Типичная ошибка: при многократной проверке одного и того же пути в рамках одного запроса file_exists() может вернуть кэшированное значение. Решение - вызывать clearstatcache() до каждой проверки или использовать is_file()/is_dir(), которые работают по тому же принципу, но специфичны для типа объекта.

Как проверить, что по указанному пути находится именно обычный файл?

Функция is_file() возвращает true только для файлов (не директорий, не символических ссылок без учёта их цели). Пример:


<?php
clearstatcache();
$path = '/tmp/log.txt';
if (is_file($path)) {
    echo 'Это файл';
} else {
    echo 'Это не файл или объект не существует';
}
?>
  

Используется, когда требуется именно файл, а не директория или ссылка.

Ошибка: is_file() для символической ссылки на файл возвращает true (если цель существует). Для проверки самой ссылки используйте is_link().

Как проверить существование директории?

is_dir() - аналог для каталогов:


<?php
$dir = __DIR__ . '/uploads';
if (is_dir($dir)) {
    echo 'Директория существует';
} else {
    echo 'Директория не найдена';
}
?>
  

Цель: убедиться, что путь ведет к каталогу перед созданием файлов внутри.

Как проверить, существует ли файл, который может быть подключён через include?

Функция stream_resolve_include_path() проверяет, найдётся ли файл в путях include:


<?php
$filename = 'config.php';
$fullPath = stream_resolve_include_path($filename);
if ($fullPath !== false) {
    echo 'Файл будет найден по пути: ' . $fullPath;
} else {
    echo 'Файл не доступен для подключения';
}
?>
  

Полезна для автозагрузчика или проверки перед require_once.

Проблема: функция не проверяет права доступа на чтение, только существование в путях include.

Как получить информацию о файле и одновременно проверить его существование?

Использование stat() или fileatime() с последующей проверкой на false:


<?php
$stat = @stat('/etc/hosts');
if ($stat !== false) {
    echo 'Файл существует, размер: ' . $stat['size'] . ' байт';
} else {
    echo 'Файл не существует или недоступен';
}
?>
  

Подходит, если нужна дополнительная информация (размер, время изменения).

Ошибка: при отсутствии файла stat() выдаёт предупреждение, поэтому используется оператор подавления ошибок @. Решение: предварительно проверить file_exists() или использовать clearstatcache().

Как проверить существование файла и его доступность для чтения?

Попытка открыть файл через fopen() в режиме 'r':


<?php
$handle = @fopen('/var/log/syslog', 'r');
if ($handle) {
    fclose($handle);
    echo 'Файл существует и доступен для чтения';
} else {
    echo 'Файл не существует или нет прав на чтение';
}
?>
  

Используется, когда необходимо не только существование, но и возможность чтения.

Минус: создаёт дескриптор файла, который нужно закрыть. При большом количестве проверок может быть накладным.

Как учесть возможное кэширование при повторных проверках?

Проблема функций файловой системы - кэширование результатов. Решение - вызов clearstatcache() перед каждой проверкой или для указанного пути:


<?php
// Первая проверка
$first = file_exists('/tmp/data.lock');
// ... какой-то код, возможно меняющий файл
clearstatcache(true, '/tmp/data.lock');
$second = file_exists('/tmp/data.lock');
?>
  

Обязательно для длительных скриптов.

Ошибка: забыть сбросить кэш. Решение: всегда вызывать clearstatcache() перед серией проверок одного пути.

Расширенные примеры проверки существования

Далее приведены более сложные и редкие сценарии использования проверки существования в PHP.

Пример 1. Проверка с использованием кэширования и массовых проверок

Сброс кэша только для конкретного пути, чтобы не затрагивать остальную статистику:

Пример

<?php
$paths = ['config.php', 'lib.php', 'cache/'];
$results = [];
foreach ($paths as $path) {
    clearstatcache(true, $path);
    if (is_file($path)) {
        $results[$path] = 'file';
    } elseif (is_dir($path)) {
        $results[$path] = 'dir';
    } else {
        $results[$path] = 'not found';
    }
}
print_r($results);
?>
Array
(
    [config.php] => file
    [lib.php] => file
    [cache/] => dir
)

Пояснение: для каждого пути выполняется индивидуальный сброс кэша, что гарантирует свежесть данных.

Пример 2. Проверка существования файлов по маске (glob)

Комбинирование glob() и file_exists() для проверки наличия файлов с определённым расширением:

Пример

<?php
$pattern = __DIR__ . '/logs/*.log';
$files = glob($pattern);
if ($files) {
    echo 'Найдено ' . count($files) . ' лог-файлов';
} else {
    echo 'Нет файлов с расширением .log';
}
?>
Найдено 3 лог-файлов

Пояснение: функция glob() возвращает только существующие файлы, что избавляет от дополнительных проверок.

Пример 3. Проверка удалённых файлов (через URL)

Проверка существования файла на удалённом сервере (HTTP/HTTPS) с помощью get_headers():

Пример

<?php
$url = 'https://example.com/update.xml';
$headers = @get_headers($url);
if (stripos($headers[0], '200 OK') !== false) {
    echo 'Файл существует на удалённом сервере';
} else {
    echo 'Файл не найден (HTTP ' . $headers[0] . ')';
}
?>
Файл существует на удалённом сервере

Пояснение: используется для проверки доступности обновлений или внешних ресурсов.

Пример 4. Обход символьных ссылок

Проверка существования цели символьной ссылки с разрешением конечного файла:

Пример

<?php
$link = '/tmp/symlink_to_config';
if (is_link($link)) {
    $real = realpath($link);
    if ($real !== false) {
        echo 'Ссылка ведёт на: ' . $real . ' - ';
        echo is_file($real) ? 'файл' : (is_dir($real) ? 'директория' : 'неизвестный тип');
    } else {
        echo 'Цель ссылки не существует';
    }
} else {
    echo 'Это не символьная ссылка';
}
?>
Ссылка ведёт на: /etc/config.ini - файл

Пояснение: realpath() разрешает ссылку и проверяет существование конечного объекта.

Пример 5. Использование итератора DirectoryIterator для проверки существования

Проверка, существует ли файл в конкретной директории, с помощью итератора:

Пример

<?php
$dir = new DirectoryIterator('/var/www/images');
$targetFile = 'logo.png';
$found = false;
foreach ($dir as $fileinfo) {
    if ($fileinfo->isFile() && $fileinfo->getFilename() === $targetFile) {
        $found = true;
        echo 'Файл найден, размер: ' . $fileinfo->getSize() . ' байт';
        break;
    }
}
if (!$found) {
    echo 'Файл отсутствует в директории';
}
?>
Файл найден, размер: 123456 байт

Пояснение: позволяет дополнительно получить свойства файла без отдельного вызова stat().

Пример 6. Пакетная проверка с учётом прав доступа

Проверка существования и прав на запись для нескольких файлов с записью проблем в массив:

Пример

<?php
$files = ['data.csv', 'config.ini', 'temp/'];
$errors = [];
foreach ($files as $file) {
    clearstatcache(true, $file);
    if (!file_exists($file)) {
        $errors[] = "$file не существует";
        continue;
    }
    // Дополнительная проверка на запись
    if (is_writable($file)) {
        continue;
    }
    $errors[] = "$file недоступен для записи";
}
if (empty($errors)) {
    echo 'Все объекты существуют и доступны для записи';
} else {
    echo implode('\n', $errors);
}
?>
data.csv не существует
config.ini недоступен для записи

Пояснение: каждая ошибка отдельно обрабатывается, что удобно для отладки.

Проверка существования в PHP - comments

En
Exist php (php)