Scandir on steroids:
For when you want to filter your file list, or only want to list so many levels of subdirectories...
// start search in $path (defaults to current working directory)
// return $types: 2 => files; 1 => directories; 3 => both;
// $levels: 1 => look in the $path only; 2 => $path and all children;
// 3 => $path, children, grandchildren; 0 => $path and all subdirectories;
// less than 0 => complement of -$levels, OR everything starting -$levels down
// e.g. -1 => everthing except $path; -2 => all descendants except $path + children
// Remaining argument(s) is(are) a filter array(list) of regular expressions which operate on the full path.
// First character (before the '/' of the regExp) '-' => NOT.
// First character (after a possible '-') 'd' => apply to directory name
// The filters may be passed in as an array of strings or as a list of strings
// Note that output directories are prefixed with a '*' (done in the line above the return)$dS=DIRECTORY_SEPARATOR;
if (!($path=realpath($path?$path:getcwd()))) return array();// bad path
// next line rids terminating \ on drives (works since c: == c:\ on PHP). OK in *nix?if (substr($path,-1)==$dS)$path=substr($path,0,-1);
if (is_null($types))$types=2;
if (is_null($levels))$levels=1;
if (is_null($aFilter))$aFilter=array();// last argument may be passed as a list or as an array$aFilter=array_slice(func_get_args(),3);
if ($aFilter&&gettype($aFilter[0])=="array")$aFilter=$aFilter[0];$adFilter= array();// now move directory filters to separate array:foreach ($aFilteras$i=>$filter)// for each directory filter...if (($pos=stripos("$filter","d")) &&$pos<3) {// next line eliminates the 'd'$adFilter[] =substr($filter,0,$pos-1) .substr($filter,$pos);
unset($aFilter[$i]); }$aFilter=array_merge($aFilter);// reset indeces$aRes= array();// results, $aAcc is an Accumulator$aDir= array($path);// dirs to checkfor ($i=$levels>0?$levels++:-1;($aAcc=array())||$i--&&$aDir;$aDir=$aAcc)
while ($dir=array_shift($aDir))
foreach (scandir($dir) as$fileOrDir)
if ($fileOrDir!="."&&$fileOrDir!="..") {
if ($dirP=is_dir($rp="$dir$dS$fileOrDir"))
if (pathFilter("$rp$dS",$adFilter))$aAcc[] =$rp;
if ($i
if (pathFilter($rp,$aFilter))$aRes[] = ($dirP?"*":"") .$rp; }
return$aRes;
}?>
example usage:
define("_",NULL);// this will find all non .jpg, non .Thumbs.db files under c:\Photo$aFiles=dirList('c:\Photo',_,0,'-/\.jpg$/i','-/\\\\Thumbs.db$/');$aFiles=dirList();// find the files in the current directory
// next lines will find .jpg files in non Photo(s) subdirectories, excluding Temporary Internet Filesset_time_limit(60);// iterating from the top level can take a while$aFiles=dirList("c:\\",_,0,'/\.jpg$/i','-d/\\\\Photos?$/i','-d/Temporary Internet/i');?>
Note that this function will consume a lot of time if scanning large
directory structures (which is the reason for the '[-]d/.../' filters).
Csaba Gabor from Vienna