jackmn1 Posted August 20, 2010 Share Posted August 20, 2010 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: 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 Quote Link to comment Share on other sites More sharing options...
kickstart Posted August 20, 2010 Share Posted August 20, 2010 Hi Quick play and something like this should do it <?php function find($dir, $pattern) { $dir = escapeshellcmd($dir); $files = glob("$dir/$pattern"); $retvar = false; if ($files) { $retvar = true; } else { foreach (glob("$dir/{.[^.]*,*}", GLOB_BRACE|GLOB_ONLYDIR) as $sub_dir) //look in subdirectories { $retvar = $retvar || find($sub_dir, $pattern); //recursive call if ($retvar) break; } } return $retvar; } if ($txtFiles=find("project/sys/diagram","*.txt")) echo "Folder project/sys/diagram contains a text file<br />" ; if ($txtFiles=find("project/sys/bin","*.txt")) echo "Folder project/sys/bin contains a text file<br />" ; if ($txtFiles=find("project/sys/scripts","*.txt")) echo "Folder project/sys/scripts contains a text file<br />" ; if ($txtFiles=find("project/sys/styles","*.txt")) echo "Folder project/sys/styles contains a text file<br />" ; if ($txtFiles=find("project/sys/meta","*.txt")) echo "Folder project/sys/meta contains a text file<br />" ; ?> Call it with the base directory name and it will search through sub directories until it finds a text file at which point it will break out of the loop and come back with true. All the best Keith Quote Link to comment Share on other sites More sharing options...
jackmn1 Posted August 20, 2010 Author Share Posted August 20, 2010 Thanks, kickstart, that helps a lot. But the folders I listed are just an example and there are in fact many many more subfolders to project/sys. Therefore I need to somehow find the subfolder list (only 1st level children), and loop through that list instead of the: if ($txtFiles=find("project/sys/diagram","*.txt")) echo "Folder project/sys/diagram contains a text file<br />" ; if ($txtFiles=find("project/sys/bin","*.txt")) echo "Folder project/sys/bin contains a text file<br />" ; if ($txtFiles=find("project/sys/scripts","*.txt")) echo "Folder project/sys/scripts contains a text file<br />" ; Can you show me how to do this? Quote Link to comment Share on other sites More sharing options...
kickstart Posted August 20, 2010 Share Posted August 20, 2010 Hi This will find all the subdirectories of the current directory that contains a text file <?php function find($dir, $pattern) { $dir = escapeshellcmd($dir); $files = glob("$dir/$pattern"); $retvar = false; if ($files) { $retvar = true; } else { foreach (glob("$dir/{.[^.]*,*}", GLOB_BRACE|GLOB_ONLYDIR) as $sub_dir) //look in subdirectories { $retvar = $retvar || find($sub_dir, $pattern); //recursive call if ($retvar) break; } } return $retvar; } $dir = "./"; // Open a current directory and proceed to read its contents if (is_dir($dir)) { if ($dh = opendir($dir)) { while (($file = readdir($dh)) !== false) { if ($file != '.' && $file != '..' && is_dir($file)) { if ($txtFiles=find($dir.$file,"*.txt")) echo "Folder $dir$file contains a text file<br />" ; } } closedir($dh); } } ?> Set $dir to another directory if you do not want to use it on the current directory. All the best Keith Quote Link to comment Share on other sites More sharing options...
jackmn1 Posted August 20, 2010 Author Share Posted August 20, 2010 Great! but the function doesn't output anything, and after debugging, I found out that for some reason it doesn't meet the condition "is_dir". Do you have any idea what might be the reason? Quote Link to comment Share on other sites More sharing options...
kickstart Posted August 20, 2010 Share Posted August 20, 2010 Hi Not sure. Tried it on my PC and it worked OK is_dir is a standard php function to determine if something is a directory. Take out the checks for ".." and "." and double check (including those directories will give some spurious extra lines). All the best Keith Quote Link to comment Share on other sites More sharing options...
jackmn1 Posted August 20, 2010 Author Share Posted August 20, 2010 I did remove the ".." and "." conditions, but is_dir still doesn't work :-( Quote Link to comment Share on other sites More sharing options...
kickstart Posted August 20, 2010 Share Posted August 20, 2010 Hi Looking around there seem to be a fair few people having problems with is_dir depending on file systems, versions of php, etc. One cheat might be to check instead that something isn't a file:- if ($file != '.' && $file != '..' && !is_file($file)) That works on my machine (but then so did is_dir). Give it a try. All the best Keith Quote Link to comment Share on other sites More sharing options...
jackmn1 Posted August 20, 2010 Author Share Posted August 20, 2010 This seems to work a lot better, however, I now noticed that it works only if I leave the $dir variable as $dir = "./", but it doesn't work with $dir = "./project/sys". This is strange, maybe I'm entering the path incorrectly (I'm still a newbie in PHP..). Quote Link to comment Share on other sites More sharing options...
kickstart Posted August 20, 2010 Share Posted August 20, 2010 Hi Is projects a sub directory of the directory the script is in? If so them just put an extra / after sys. All the best Keith Quote Link to comment Share on other sites More sharing options...
jackmn1 Posted August 20, 2010 Author Share Posted August 20, 2010 the script is located in the folder project/extra/scripts/index.php. So what should $dir value be? Quote Link to comment Share on other sites More sharing options...
kickstart Posted August 20, 2010 Share Posted August 20, 2010 Hi It needs to point at the directory you want to search. Ie, assuming project/sys/ is in the root directory then you would need $dir = '/project/sys'; Could also be relative, $dir = '../../../'; All the best Keith Quote Link to comment Share on other sites More sharing options...
jackmn1 Posted August 20, 2010 Author Share Posted August 20, 2010 It works! it wasn't the path eventually, I just realized that there was another is_dir I needed to change to !is_file now. Thanks a lot, kickstart. I appreciate your help. Quote Link to comment Share on other sites More sharing options...
kickstart Posted August 20, 2010 Share Posted August 20, 2010 Hi Glad you got it working. If you want to see a script take ages, run it against the root directory . All the best Keith Quote Link to comment Share on other sites More sharing options...
jackmn1 Posted August 20, 2010 Author Share Posted August 20, 2010 :-) Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.