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

Time:05-06

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