Method to recursively search for a file in directory and subdirectories doesn't find the file

120

Question: Method to recursively search for a file in directory and subdirectories doesn't find the file

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;         } 

Total Answers: 2

75

Answers 1: of Method to recursively search for a file in directory and subdirectories doesn't find the file

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;         }  
53

Answers 2: of Method to recursively search for a file in directory and subdirectories doesn't find the file

   * 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 : [];