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.
Parameters
$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:
- 'nomask': The preg_match() regular expression of the files to ignore. Defaults to '/(\.\.?|CVS)$/'.
- 'callback': The callback function to call for each match. There is no default callback.
- 'recurse': When TRUE, the directory scan will recurse the entire tree starting at the provided directory. Defaults to TRUE.
- 'key': The key to be used for the returned associative array of files. Possible values are 'uri', for the file's URI; 'filename', for the basename of the file; and 'name' for the name of the file without the extension. Defaults to 'uri'.
- 'min_depth': Minimum depth of directories to return files from. Defaults to 0.
$depth: Current depth of recursion. This parameter is only used internally and should not be passed in.
Return value
An associative array (keyed on the chosen key) of objects with 'uri', 'filename', and 'name' members corresponding to the matching files.
Related topics
File
- includes/
file.inc, line 2022 - API for handling file uploads and server file management.
Code
<?php
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,
);
$options['key'] = in_array($options['key'], array('uri', 'filename', 'name')) ? $options['key'] : 'uri';
$files = array();
if (is_dir($dir) && $handle = opendir($dir)) {
while (FALSE !== ($filename = readdir($handle))) {
if (!preg_match($options['nomask'], $filename) && $filename[0] != '.') {
$uri = "$dir/$filename";
$uri = file_stream_wrapper_uri_normalize($uri);
if (is_dir($uri) && $options['recurse']) {
// 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);
}
return $files;
}
?> Login or register to post comments
Comments
uri's don't pass file_valid_uri()
The uri's that file_scan_directory returns don't pass
file_valid_uri().Which is a bit confusing...
It returns e.g. sites/all/modules/custom/imgimp/pics/test.jpg instead of a string that starts with public://
Fixed already?
The URIs I get from file_scan_directory() are in the
public://old_product_images/1359b.jpgform, so it might be a bug in an earlier vresion you encountered…absolute path?
Does the $dir parameter need to be an absolute path, a relative path, or either?
Retrieving all fiiles of a certain type
The mask can be tricking if you are not great in regular expressions.
Here is an example of retrieving all files from a directory and it's sub-directories that are PDF's.
<?php$dir = "/some/dir"
$files = file_scan_directory($dir, '/.*\.pdf$/');
?>
The return format is
array("/full/file/path/" => stdClass
->uri
->filename
->name
)
For the ones who would need it
After googling and inflectin Drupal in many bad ways, I've found out how to get the files within the default directory:
$files = file_scan_directory('public://fm_video', '/^.*\.(mov|mp4|avi|MOV|MP4|AVI)$/');
where fm_video must have read rights. If you would need only one file type use the '/.*\.jpg$/' like:
$files = file_scan_directory('public://fm_video', '/.*\.jpg$/');
Since regex is a realy difficult thing, I don't undestand the joke of Drupal developers to use mandatorily in a basic function. Hope this will help you further.