glob function recursive question

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
jackmn1
Forum Newbie
Posts: 9
Joined: Thu Jul 01, 2010 4:49 am

glob function recursive question

Post by jackmn1 »

I need to create a function that lists subfolders of a given folder, that contain at least one .txt file.
I found the following function, which displays a list of file that match a pattern in a directory tree:

Code: Select all

function find($dir, $pattern){
	$dir = escapeshellcmd($dir);  
	$files = glob("$dir/$pattern");  
	foreach (glob("$dir/{.[^.]*,*}", GLOB_BRACE|GLOB_ONLYDIR) as $sub_dir) //look in subdirectories
	{
		$arr   = find($sub_dir, $pattern); //recursive call
		$files = array_merge($files, $arr); // merge array with files from subdirectory  
	}  
	return $files;  
}  
$txtFiles=find("project/sys","*.txt");
foreach ($txtFiles as $txtFile)
	{
	echo '<h2>'.$txtFile.'</h2>'; //display all text files
	}
My question is, how do I change the function to return only folders that contain at least one text file. But, the functions should look inside child folders of "project/sys" and list a child folder only once if that folder or any of its child folders contain at least one text file.

I'll give an example of the output I'm looking for:
Folder list
project/sys/diagram
project/sys/bin
project/sys/scripts
project/sys/styles
project/sys/meta

The above folders may not contain a text file directly, but their children folders do. However, I'm not interested in their children folder and I want to list the above level folder only once for each folder.

Thanks in advance
NModern
Forum Newbie
Posts: 11
Joined: Fri Aug 20, 2010 2:31 am

Re: glob function recursive question

Post by NModern »

you can use an array and everytime before echo check is this folder already in array or not.
jackmn1
Forum Newbie
Posts: 9
Joined: Thu Jul 01, 2010 4:49 am

Re: glob function recursive question

Post by jackmn1 »

Thanks, but how do I control the depth level I'm in in the recursion? I need to this this condition in the second level.
Can you please show me an example of how it should look?
NModern
Forum Newbie
Posts: 11
Joined: Fri Aug 20, 2010 2:31 am

Re: glob function recursive question

Post by NModern »

Code: Select all

function find($dir, $pattern){
    $dir = escapeshellcmd($dir);  
    $files = glob("$dir/$pattern");  
    foreach (glob("$dir/{.[^.]*,*}", GLOB_BRACE|GLOB_ONLYDIR) as $sub_dir) //look in subdirectories
    {
            $arr   = find($sub_dir, $pattern); //recursive call
            $files = array_merge($files, $arr); // merge array with files from subdirectory  
    }  
    return $files;  
}  
$txtFiles=find("project/sys/","*.txt");
$path_array = array();
foreach ($txtFiles as $txtFile)
{
	$path_info = pathinfo($txtFile);
	if(!in_array($path_info['dirname'],$path_array)){
	$path_array[] = $path_info['dirname'];
	echo '<h2>'.$path_info['dirname'].'</h2>'; //display all text files
	}
}
jackmn1
Forum Newbie
Posts: 9
Joined: Thu Jul 01, 2010 4:49 am

Re: glob function recursive question

Post by jackmn1 »

Thanks. However, since my directory is huge, it will take too much time because it lists all possibilities in the array and only after wards output the unique values, right? What I wanted was to break the recursive loop after the first file is found, do you know how can I do it?
NModern
Forum Newbie
Posts: 11
Joined: Fri Aug 20, 2010 2:31 am

Re: glob function recursive question

Post by NModern »

Here is all in one function for you, returns an array

Code: Select all

$files_in_folder = array();
function filesInDir($tdir, $subdir, $src_param="*"){
	global $files_in_folder;
	if(is_dir($tdir)){
        $dirs = scandir($tdir);
        foreach($dirs as $file){

        	$file = str_replace($tdir."/", "", $file);
		    if (($file == '.')||($file == '..')){
            }elseif (is_dir($tdir.'/'.$file) && $subdir==true){
				filesInDir($tdir.'/'.$file, true, $src_param, true);
            }else{
            	$glob_files = glob($tdir."/".$src_param);
            	if(in_array($tdir."/".$file, $glob_files) && !in_array($tdir."/",$files_in_folder)){
            		$files_in_folder[] = $tdir."/";
            	}
            }
		}
	}
    return $files_in_folder;
}
print_r(filesInDir("./a",true,"*.txt"));
jackmn1
Forum Newbie
Posts: 9
Joined: Thu Jul 01, 2010 4:49 am

Re: glob function recursive question

Post by jackmn1 »

I appreciate it, but it still returns all the subfolders while what I need is to list only the first children level of project/sys and not all the 2nd and 3rd levels.
NModern
Forum Newbie
Posts: 11
Joined: Fri Aug 20, 2010 2:31 am

Re: glob function recursive question

Post by NModern »

aaaa I understood. wait second
NModern
Forum Newbie
Posts: 11
Joined: Fri Aug 20, 2010 2:31 am

Re: glob function recursive question

Post by NModern »

Code: Select all

$files_in_folder = array();
$sm_string = "";
function filesInDir($tdir, $subdir, $src_param="*"){
        global $files_in_folder,$sm_string;
        if($sm_string==""){
        	$sm_string = $tdir;
        }
        if(is_dir($tdir)){
        $dirs = scandir($tdir);
        foreach($dirs as $file){

                $file = str_replace($tdir."/", "", $file);
                    if (($file == '.')||($file == '..')){
            }elseif (is_dir($tdir.'/'.$file) && $subdir==true && $sm_string==$tdir){
                                filesInDir($tdir.'/'.$file, true, $src_param, true);
            }else{
                $glob_files = glob($tdir."/".$src_param);
                if(in_array($tdir."/".$file, $glob_files) && !in_array($tdir."/",$files_in_folder)){
                        $files_in_folder[] = $tdir."/";
                }
            }
                }
        }
    return $files_in_folder;
}
print_r(filesInDir("./blah/blah/",true,"*.txt"));
jackmn1
Forum Newbie
Posts: 9
Joined: Thu Jul 01, 2010 4:49 am

Re: glob function recursive question

Post by jackmn1 »

Works better, but still, now it returns only 1st level folders that have text files directly in them. I need it to return all folders that are 1st level children and have at least one file contained directly in them or in any of their subfolders.

For example, it returns:
"project/sys/bin" because there is a file "project/sys/bin/f_index.txt"
but it doesn't return "project/sys/media" even though there is a file called "project/sys/media/files/imageList.txt".
(note that this file is contained in 2nd level subfolder and not in the 1st level).

If I knew PHP better I would have solved it, but I don't...so any help is appreciated.
Post Reply