Finds all files that match a given mask in a given directory.
Directories and files beginning with a period are excluded; this prevents hidden files and directories (such as SVN working directories) from being scanned.
$dir: The base directory or URI to scan, without trailing slash.
$mask: The preg_match() regular expression of the files to find.
$options: An associative array of additional options, with the following elements:
$depth: Current depth of recursion. This parameter is only used internally and should not be passed in.
An associative array (keyed on the chosen key) of objects with 'uri', 'filename', and 'name' members corresponding to the matching files.
function file_scan_directory($dir, $mask, $options = array(), $depth = 0) {
// Merge in defaults.
$options += array(
'nomask' => '/^CVS$/',
'callback' => 0,
'recurse' => TRUE,
'key' => 'uri',
'min_depth' => 0,
);
// Normalize $dir only once.
if ($depth == 0) {
$dir = file_stream_wrapper_uri_normalize($dir);
$dir_has_slash = substr($dir, -1) === '/';
}
$options['key'] = in_array($options['key'], array(
'uri',
'filename',
'name',
)) ? $options['key'] : 'uri';
$files = array();
// Avoid warnings when opendir does not have the permissions to open a
// directory.
if (is_dir($dir)) {
if ($handle = @opendir($dir)) {
while (FALSE !== ($filename = readdir($handle))) {
// Skip this file if it matches the nomask or starts with a dot.
if ($filename[0] != '.' && !preg_match($options['nomask'], $filename)) {
if ($depth == 0 && $dir_has_slash) {
$uri = "{$dir}{$filename}";
}
else {
$uri = "{$dir}/{$filename}";
}
if ($options['recurse'] && is_dir($uri)) {
// Give priority to files in this folder by merging them in after
// any subdirectory files.
$files = array_merge(file_scan_directory($uri, $mask, $options, $depth + 1), $files);
}
elseif ($depth >= $options['min_depth'] && preg_match($mask, $filename)) {
// Always use this match over anything already set in $files with
// the same $options['key'].
$file = new stdClass();
$file->uri = $uri;
$file->filename = $filename;
$file->name = pathinfo($filename, PATHINFO_FILENAME);
$key = $options['key'];
$files[$file->{$key}] = $file;
if ($options['callback']) {
$options['callback']($uri);
}
}
}
}
closedir($handle);
}
else {
watchdog('file', '@dir can not be opened', array(
'@dir' => $dir,
), WATCHDOG_ERROR);
}
}
return $files;
}