note 50623 modified in function.scandir by danbrown

From: Date: Thu, 28 Jan 2010 14:18:17 +0000
Subject: note 50623 modified in function.scandir by danbrown
References: 1  Groups: php.notes 
Request: Send a blank email to php-notes+get-165452@lists.php.net to get a copy of this message
Scandir on steroids: For when you want to filter your file list, or only want to list so many levels of subdirectories... <?php function dirList($path="", $types=2, $levels=1, $aFilter=array()) { // returns an array of the specified files/directories // 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 ($aFilter as $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 check for ($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<$levels-1 && ($types & (2-$dirP))) if (pathFilter($rp, $aFilter)) $aRes[] = ($dirP?"*":"") . $rp; } return $aRes; } ?> example usage: <?php 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 Files set_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 --was-- Scandir on steroids: For when you want to filter your file list, or only want to list so many levels of subdirectories... <?php function dirList($path="", $types=2, $levels=1, $aFilter=array()) { // returns an array of the specified files/directories // 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 ($aFilter as $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 check for ($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<$levels-1 && ($types & (2-$dirP))) if (pathFilter($rp, $aFilter)) $aRes[] = ($dirP?"*":"") . $rp; } return $aRes; } ?> example usage: <?php 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 Files set_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'); ?> See my earlier entry for the definition of pathFilter(...) 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 http://php.net/manual/en/function.scandir.php

« previous php.notes (#165452) next »