I wrote a function to find a file in a specific directory and its sub-directories. You can input the filename with or without extension (basename vs. filename). The second argument is the path to search in. The file is found when it is in the given directory, however, it is not found if it is in a sub-directory. I try to make use of the recusrive call of the function to look in the sub-directories. Any ideas what I am missing?
public function findFileInPathRecursive($file_to_find, $path) {
if (substr($path, -1) != "/") $path .= "/"; // Add slash at path's end
$files = scandir($path);
foreach($files as $file) {
if (substr($file, 0, 1) == ".") continue; // skip if "." or ".."
if (is_dir($path.$file)) { // if "file" is a directory, call self with the new path
$new_path = $path.$file;
return $this->findFileInPathRecursive($file_to_find, $new_path);
}
else {
if (pathinfo($file)['basename'] == $file_to_find OR pathinfo($file)['filename'] == $file_to_find) {
return $path.$file;
}
}
}
return false;
}
CodePudding user response:
I believe that return $this->findFileInPathRecursive($file_to_find, $new_path);
will cause an early return when the first subfolder does not contains the file.
You can avoid by only returning when the file is found.
if($found = $this->findFileInPathRecursive($file_to_find, $new_path)) {
return $found;
}
public function findFileInPathRecursive($file_to_find, $path) {
if (substr($path, -1) != "/") $path .= "/"; // Add slash at path's end
$files = scandir($path);
foreach($files as $file) {
if (substr($file, 0, 1) == ".") continue; // skip if "." or ".."
if (is_dir($path.$file)) { // if "file" is a directory, call self with the new path
$new_path = $path.$file;
// We only want to return file
if($found = $this->findFileInPathRecursive($file_to_find, $new_path)) {
return $found;
}
}
else {
if (pathinfo($file)['basename'] == $file_to_find OR pathinfo($file)['filename'] == $file_to_find) {
return $path.$file;
}
}
}
return false;
}
CodePudding user response:
* Search recusively for files in a base directory matching a glob pattern.
* The `GLOB_NOCHECK` flag has no effect.
* @param string $base Directory to search
* @param string $pattern Glob pattern to match files
* @param int $flags Glob flags from https://www.php.net/manual/function.glob.php
* @return string[] Array of files matching the pattern
function glob_recursive($base, $pattern, $flags = 0) {
$flags = $flags & ~GLOB_NOCHECK;
if (substr($base, -1) !== DIRECTORY_SEPARATOR) {
$base .= DIRECTORY_SEPARATOR;
}
$files = glob($base.$pattern, $flags);
if (!is_array($files)) {
$files = [];
}
$dirs = glob($base.'*', GLOB_ONLYDIR|GLOB_NOSORT|GLOB_MARK);
if (!is_array($dirs)) {
return $files;
}
foreach ($dirs as $dir) {
$dirFiles = glob_recursive($dir, $pattern, $flags);
$files = array_merge($files, $dirFiles);
}
return $files;
}
$files = glob($base.$pattern, $flags);
$files = $files !== false ? $files : [];