Updated for Version 2.4, May 17, 2020.
I originally wrote this a few (16) years ago in 2004 and never really promoted it beyond the realms of the #php IRC channel on EfNet. However, it has managed to find its way into applications such as WordPress and many other PHP apps. It is gratifying to know that others are finding it useful.
So what is preg_find() anyway? A short summary for those who have never encountered it: Imaging a recursive capable glob() with the ability to filter the results with a regex (PCRE) and various arguments to modify the results to bring back additional data.
Well today (18 April 2007) I thought I would add one commonly requested feature. Sorting. Using the power of PHP’s anonymous (lambda-style) functions, preg_find() now creates a custom sort routine based on the arguments passed in, filename, dir+filename, last modified, file size, disk usage (yes those last 2 are different) in either ascending or descending order.
Download preg_find.phps
Download preg_find.php in plain text format
A simple example to get started – we’ll work on my PHP miscellaneous code directory:
Example 1: List the files (no directories):
Code:
include 'preg_find.php'; $files = preg_find('/./', '../code'); foreach($files as $file) printf("<br>%sn", $file); |
You can see the result here
Now let us look at a recursive search – this is easy, just pass in the PREG_FIND_RECURSIVE argument.
Example 2: List the files, recursively:
Code:
$files = preg_find('/./', '../code', PREG_FIND_RECURSIVE); foreach($files as $file) printf("<br>%sn", $file); |
You can see the result here
Lets go further, this time we don’t want to see any files – only a directory structure.
Example 3: List the directory tree:
Code:
$files = preg_find('/./', '../code', PREG_FIND_DIRONLY|PREG_FIND_RECURSIVE); foreach($files as $file) printf("<br>%sn", $file); |
You can see the result here
It should be obvious by now that we are using constants as our modifier arguments. What might not be immediately obvious is that these constants are “bit” values (.e.g. 1, 2, 4, 8, 16, …, 1024, etc) and using PHP’s Bitwise Or operator “|” we can combine modifiers to pass multiple modifiers into the function.
How about a regex? Files starting with str_ and ending in .php
Example 4: Using a regex on the same code as example 1:
Code:
$files = preg_find('/^str_.*?.php$/D', '../code'); foreach($files as $file) printf("<br>%sn", $file); |
You can see the result here
What about that funky PREG_FIND_RETURNASSOC modifier?
This will change the output dramatically from a simple file/directory array to an associative array where the key is the filename, and the value is lots of information about that file.
Example5: Use of PREG_FIND_RETURNASSOC
Code:
$files = preg_find('/^str_.*?.php$/D', '../code', PREG_FIND_RETURNASSOC); foreach($files as $file) printf("<br>%sn", $file); |
You can see the result here
As I mentioned earlier, I added sorting capability to the results, so let us look at some examples of that.
Example 6. Sorting the results (of example 1)
Code:
$files = preg_find('/./', '../code', PREG_FIND_SORTKEYS); foreach($files as $file) printf("<br>%sn", $file); |
You can see the result here
Example 7. And reverse sort.
Code:
$files = preg_find('/./', '../code', PREG_FIND_SORTKEYS|PREG_FIND_SORTDESC); foreach($files as $file) printf("<br>%sn", $file); |
You can see the result here
Ok, thats all well and good, what about something more interesting?
Example 8. Finding the largest 5 files in the tree, sorted by filesize, descending.
Code:
$files = preg_find('/./', '../code', PREG_FIND_RECURSIVE|PREG_FIND_RETURNASSOC|PREG_FIND_SORTFILESIZE|PREG_FIND_SORTDESC); $i=1; foreach($files as $file => $stats) { printf('<br>%d) %d %s', $i, $stats['stat']['size'], $file); $i++; if ($i > 5) break; } |
You can see the result here.
Or what about the 10 most recently modified files?
Example 9.
Code:
$files = preg_find('/./', '../code', PREG_FIND_RECURSIVE|PREG_FIND_RETURNASSOC|PREG_FIND_SORTMODIFIED|PREG_FIND_SORTDESC); $i=1; foreach($files as $file => $stats) { printf('<br>%d) %s - %d bytes - %s', $i, date('Y-m-d H:i:s', $stats['stat']['mtime']), $stats['stat']['size'], $file); $i++; if ($i > 10) break; } |
You can see the result here.
I am keen to receive feedback on what you think of this function. If you have used it in some other application – great, I would love to know. Suggestions, improvements, criticisms are also always welcome.