Я пытаюсь думать о самом быстром способе реализации нечувствительной к регистру функции file_exists в PHP. Я предпочитаю перечислить файл в каталоге и выполнить сравнение strtolower() в strtolower(), пока не будет найдено совпадение?PHP-регистр Нечувствительная версия file_exists()
ответ
Я использовал источник комментариев, чтобы создать эту функцию. Возвращает полный файл пути, если он найден, FALSE, если нет.
Не работает без учета регистра в именах каталогов в имени файла.
function fileExists($fileName, $caseSensitive = true) {
if(file_exists($fileName)) {
return $fileName;
}
if($caseSensitive) return false;
// Handle case insensitive requests
$directoryName = dirname($fileName);
$fileArray = glob($directoryName . '/*', GLOB_NOSORT);
$fileNameLowerCase = strtolower($fileName);
foreach($fileArray as $file) {
if(strtolower($file) == $fileNameLowerCase) {
return $file;
}
}
return false;
}
Не было бы здорово ВСЕГДА вернуть полное имя файла? Это странно, когда иногда встречается логический, а иногда и полезный путь. –
Что бы вы вернули, если файл не существует? O_o – Jonathan
Я думаю, что функция 'fileExists' должна возвращать' true', если файл существует :) –
В именах файлов Unix чувствительны к регистру, поэтому вы не сможете выполнить проверку отсутствия регистра без учета содержимого каталога.
Для чистой реализации PHP да. Пример: the comments for the file_exists
function.
Другой вариант - запустить скрипт в файловой системе, не учитывающей регистр.
Спасибо! Закончилось использование этого в моем ответе. –
Ваш подход работает.
В качестве альтернативы вы можете использовать glob
, чтобы получить список всех файлов и каталогов в настоящем рабочем каталоге в массиве, используйте array_map
для применения strtolower
к каждому элементу, а затем используйте in_array
, чтобы проверить, существует ли в массиве ваш файл (после применения strtolower
) ,
Я столкнулся с тем же вопросом, когда мы перешли из IIS в apache. Ниже - кусок, который я взбивал. Он возвращает либо правильный путь как строку, либо false.
function resolve_path($path)
{
$is_absolute_path = substr($path, 0, 1) == '/';
$resolved_path = $is_absolute_path ? '/' : './';
$path_parts = explode('/', strtolower($path));
foreach ($path_parts as $part)
{
if (!empty($part))
{
$files = scandir($resolved_path);
$match_found = FALSE;
foreach ($files as $file)
{
if (strtolower($file) == $part)
{
$match_found = TRUE;
$resolved_path .= $file . '/';
}
}
if (!$match_found)
{
return FALSE;
}
}
}
if (!is_dir($resolved_path) && !is_file($resolved_path))
{
$resolved_path = substr($resolved_path, 0, strlen($resolved_path) - 1);
}
$resolved_path = $is_absolute_path ? $resolved_path : substr($resolved_path, 2, strlen($resolved_path));
return $resolved_path;
}
$relative_path = substr($_SERVER['REQUEST_URI'], 1, strlen($_SERVER['REQUEST_URI']));
$resolved_path = resolve_path($relative_path);
if ($resolved_path)
{
header('Location: http://' . $_SERVER['SERVER_NAME'] . '/' . $resolved_path);
die();
}
Я улучшил функцию John Himmelman
«s и придумали это:
suppose that i have a catch system \iMVC\kernel\caching\fileCache
function resolve_path($path)
{
# check if string is valid
if(!strlen($path)) return FALSE;
# a primary check
if(file_exists($path)) return $path;
# create a cache signiture
$cache_sig = __METHOD__."@$path";
# open the cache file
$fc = new \iMVC\kernel\caching\fileCache(__CLASS__);
# check cache file and validate it
if($fc->isCached($cache_sig) && file_exists($fc->retrieve($cache_sig)))
{
# it was a HIT!
return $fc->retrieve($cache_sig);
}
# if it is ab
$is_absolute_path = ($path[0] == DIRECTORY_SEPARATOR);
# depart the path
$path_parts = array_filter(explode(DIRECTORY_SEPARATOR, strtolower($path)));
# normalizing array's parts
$path_parts = count($path_parts)? array_chunk($path_parts, count($path_parts)) : array();
$path_parts = count($path_parts[0])?$path_parts[0]:array();
# UNIX fs style
$resolved_path = $is_absolute_path ? DIRECTORY_SEPARATOR : ".";
# WINNT fs style
if(string::Contains($path_parts[0], ":"))
{
$is_absolute_path = 1;
$resolved_path = $is_absolute_path ? "" : ".".DIRECTORY_SEPARATOR;
}
# do a BFS in subdirz
foreach ($path_parts as $part)
{
if (!empty($part))
{
$target_path = $resolved_path.DIRECTORY_SEPARATOR.$part;
if(file_exists($target_path))
{
$resolved_path = $target_path;
continue;
}
$files = scandir($resolved_path);
$match_found = FALSE;
foreach ($files as $file)
{
if (strtolower($file) == $part)
{
$match_found = TRUE;
$resolved_path = $resolved_path.DIRECTORY_SEPARATOR.$file;
break;
}
}
if (!$match_found)
{
return FALSE;
}
}
}
# cache the result
$fc->store($target_path, $resolved_path);
# retrun the resolved path
return $resolved_path;
}
Я настроил функцию лил немного больше. думаю, это лучше для использования
function fileExists($fileName, $fullpath = false, $caseInsensitive = false)
{
// Presets
$status = false;
$directoryName = dirname($fileName);
$fileArray = glob($directoryName . '/*', GLOB_NOSORT);
$i = ($caseInsensitive) ? "i" : "";
// Stringcheck
if (preg_match("/\\\|\//", $fileName)) // Check if \ is in the string
{
$array = preg_split("/\\\|\//", $fileName);
$fileName = $array[ count($array) -1 ];
}
// Compare String
foreach ($fileArray AS $file)
{
if(preg_match("/{$fileName}/{$i}", $file))
{
$output = "{$directoryName}/{$fileName}";
$status = true;
break;
}
}
// Show full path
if($fullpath && $status)
$status = $output;
// Return the result [true/false/fullpath (only if result isn't false)]
return $status;
}
Найдя эту страницу с быстрой гугле я использовал Kirk
«s решение, однако это медленно, если вы называете его несколько раз на одной и той же директории, или директории, который имеет большое количество файлов в . Это связано с его циклом по всем файлам каждый раз, поэтому я оптимизировал его немного:
function fileExists($fileName) {
static $dirList = [];
if(file_exists($fileName)) {
return true;
}
$directoryName = dirname($fileName);
if (!isset($dirList[$directoryName])) {
$fileArray = glob($directoryName . '/*', GLOB_NOSORT);
$dirListEntry = [];
foreach ($fileArray as $file) {
$dirListEntry[strtolower($file)] = true;
}
$dirList[$directoryName] = $dirListEntry;
}
return isset($dirList[$directoryName][strtolower($fileName)]);
}
Я уронил флаг для проверки нечувствительности к регистру, как я полагаю, вы бы просто использовать file_exists
если вы Ждут» Это нужно, поэтому флаг казался излишним. Я также ожидаю, что если вы делаете что-либо помимо тривиального сценария, вы хотели бы превратить это в класс, чтобы получить больше контроля над кешированием списка каталогов, например. перезагружая его, но это выходит за рамки того, что мне нужно, и это должно быть тривиально, если вам это нужно.
Этот вопрос несколько лет, но он связан с дубликатами, поэтому здесь приведен простой метод.
Возвращает false
если $filename
в любом случае не будет найден в $path
или фактическое имя файла первого файла, возвращаемый glob()
, если оно было найдено в любом случае:
$result = current(preg_grep("/$filename$/i", glob("$path/*")));
Снимите current()
вернуть все совпадающие файлы. Это важно для файловых систем, чувствительных к регистру, поскольку могут существовать IMAGE.jpg
и image.JPG
.
Моего настроенное решения, независимая от ОС, case-insensitive realpath()
альтернативы, охватывающее весь путь, названный realpathi()
:
/**
* Case-insensitive realpath()
* @param string $path
* @return string|false
*/
function realpathi($path)
{
$me = __METHOD__;
$path = rtrim(preg_replace('#[/\\\\]+#', DIRECTORY_SEPARATOR, $path), DIRECTORY_SEPARATOR);
$realPath = realpath($path);
if ($realPath !== false) {
return $realPath;
}
$dir = dirname($path);
if ($dir === $path) {
return false;
}
$dir = $me($dir);
if ($dir === false) {
return false;
}
$search = strtolower(basename($path));
$pattern = '';
for ($pos = 0; $pos < strlen($search); $pos++) {
$pattern .= sprintf('[%s%s]', $search[$pos], strtoupper($search[$pos]));
}
return current(glob($dir . DIRECTORY_SEPARATOR . $pattern));
}
поиск файла с Glob [nN][aA][mM][eE]
шаблоном, кажется, быстрым решением
Остальных ответов могут быть очень ресурсоемкими в больших файловых системах (большое количество файлов для поиска). Возможно, было бы полезно создать временную таблицу всех имен файлов (если необходимо, полный путь). Затем выполните аналогичный поиск в этой таблице, чтобы получить все, что имеет место.
SELECT actual_file_name
FROM TABLE_NAME
WHERE actual_file_name LIKE 'filename_i_want'
//will resolve & print the real filename
$path = "CaseInsensitiveFiLENAME.eXt";
$dir = "nameOfDirectory";
if ($handle = opendir($dir)) {
while (false !== ($entry = readdir($handle))) {
if (strtolower($path) == strtolower($entry)){
echo $entry ;
}}
closedir($handle);
}
Просто натыкался на это сегодня, но не понравился ни один из ответов здесь, так что я думал, что я хотел бы добавить свое решение (с помощью SPL и регулярное выражение итератор)
function _file_exists($pathname){
try{
$path = dirname($pathname);
$file = basename($pathname);
$Dir = new \FilesystemIterator($path, \FilesystemIterator::UNIX_PATHS);
$regX = new \RegexIterator($Dir, '/(.+\/'.preg_quote($file).')$/i', \RegexIterator::MATCH);
foreach ($regX as $p) return $p->getPathname();
}catch (\UnexpectedValueException $e){
//invalid path
}
return false;
}
способ я использую его, как так:
$filepath = 'path/to/file.php';
if(false !== ($filepath = _file_exists($filepath))){
//do something with $filepath
}
таким образом, он будет использовать встроенный в один первый, если это не будет использовать модули и присвоить надлежащую оболочку переменной $filepath
.
- 1. JsGrid нечувствительная ошибка
- 2. PHP file_exists
- 3. C# Нечувствительная к регистру строка
- 4. Laravel нечувствительная к регистру локализация
- 5. Underscore.js Нечувствительная к регистру сортировка
- 6. Нечувствительная к регистру строка :: find
- 7. Почему file_exists() возвращает false?
- 8. Предупреждение: file_exists(): ERROR
- 9. file_exists() не находит файл
- 10. PHP file_exists IF Синтаксис
- 11. Обновление расширения MediaWiki, file_exists()
- 12. PHP file_exists directory
- 13. file_exists всегда возвращает false
- 14. Codeigniter "file_exists ($ filename)"
- 15. file_exists() не работает codeigniter
- 16. PHP rename() file_exists()
- 17. file_exists всегда false
- 18. php direct path file_exists()
- 19. file_exists() не работает
- 20. PHP Phar - file_exists() issue
- 21. Странное поведение от file_exists
- 22. file_exists в PHP
- 23. PHP file_exists не работает
- 24. PHPUnit не распознает file_exists()
- 25. Php file_exists не работает
- 26. php weird file_exists ошибка
- 27. Если file_exists Smarty
- 28. Использование file_exists в inputfilter
- 29. Нечувствительная ошибка Неопределенные символы для архитектуры armv7
- 30. Произвольная и нечувствительная строка внутри кодового блока
вещь, файл_exists IS нечувствителен к регистру – Dwza
-1 - для этого требуется уточнение. Это для файловой системы, чувствительной к регистру. Если нет, то вопрос вздор, поскольку PHP 'file_exists()' не учитывает регистр для файлов в нечувствительных к регистру файловых системах. – danorton