0

I have a server folder with a large number of files, randomly named with a guid value (example file: c3c1a48e-a798-41bd-bd70-66ffdc619963.jpg ).

I need to do a case-insensitive search of that folder, as there might be an uppercase (or mixed case) version of the same filename. (I cannot convert existing files to all lowercase file names.)

The answers in this question PHP Case Insensitive Version of file_exists() provide a function (shown below) that will 'glob' the entire folder into an array, then does a foreach search each item in the array.

This would seem to be a bit slow/inefficient, especially when searching a folder with many (thousands) of files.

Is there a more efficient way to do a case-insensitive filename search? Or is the use of the foreach loop - as shown in the below code - 'efficient enough'?

(This is the code recommended by the above question)

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;

}

Rick Hellewell
  • 1,032
  • 11
  • 34
  • Do some profiling. A loop obviously takes its toll (over pre-lowercasing per `array_map` or simply using `preg_grep`). If it has any relevance, a database-cached list of filenames would also be a trivial workaround. – mario Aug 31 '18 at 00:44
  • (Oh I see, this was already answered - if you read past the first answer!) – mario Aug 31 '18 at 00:45
  • There's another answer to that question that calls `readdir()` in a loop, so it doesn't have to read all the filenames at once. This could be better for a huge directory. – Barmar Aug 31 '18 at 02:01

1 Answers1

0

I cannot comment, though this can be an answer to your question: No. As of right now in your current state, it looks like you have to use that logic. -However- you could create logic to take those files that have capital letters and use copy($filename,strtolower($filename)) in the folder to make them lower case and then remove the old filenames that have capital letters. . Then in the future upon adding more files to the many, strtolower($new_file_name) before adding the file to the system. I agree with you though that that logic does seem slow, especially with thousands of files.

It contradicts you saying you cannot rename /convert the file names, though once you do it, that will be the only time you would have to rename them.

Zac
  • 1,719
  • 3
  • 27
  • 48
  • Re renaming files: the file names are also stored in a database, and there may be 'collisions' in the file name due to the way the filenames were originally created when they were stored as filenames and as entries in the database. So a rename of files would cause other possible problems. – Rick Hellewell Aug 31 '18 at 01:35
  • If using SQL database you can rename the records while also at the same time of renaming all the file, using a variable such as `$file_name` and then (mysql example) executing `UPDATE [table] SET file_name = $file_name WHERE condition....;` – Zac Aug 31 '18 at 02:09
  • Well, yes, I could change entries in the database. But that doesn't take care of possible 'collisions' that already exist. And the question is about the most efficient way to do a case-insensitive search of filenames, not about changing or syncing the database. – Rick Hellewell Aug 31 '18 at 16:44