Tutorial Details
- Technology: PHP
- Estimated Completion Time: 5-10 Minutes
Are you still using opendir() to loop through folders in PHP? Doesn’t that require a lot of repetitive code everytime you want to search a folder? Luckily, PHP’s glob() is a much smarter solution.
Introduction
Here’s an example of echoing out some information from a folder, using the traditional opendir() function.
$dir = "/etc/php5/";
// Open a known directory, and proceed to read its contents
if (is_dir($dir))
{
if ($dh = opendir($dir))
{
while (($file = readdir($dh)) !== false)
{
echo "filename: $file : filetype: " . filetype($dir . $file) . "\n";
}
closedir($dh);
}
}
That should look somewhat familiar. We can massively shorten the code above with:
$dir = "/etc/php5/*";
// Open a known directory, and proceed to read its contents
foreach(glob($dir) as $file)
{
echo "filename: $file : filetype: " . filetype($file) . "<br />";
}
Isn’t that much easier? Eager to learn how the method works? If yes, then let’s get on with it.
glob() supports a total of two arguments, with the second argument being optional. The first argument is the path to the folder, however, it’s a bit more powerful than that.
Step 1. The First Argument
This first argument supports a pattern. This means that you can limit the search to specific filetypes or even multiple directories at the same time by using multiple asterixes “*”. Let’s assume that you have a website that allows users to upload images (just because I read this). Each user has his/her own folder within the folder “userImages.” Inside these folder are two additional folders, called “HD” and “TN,” for high definition (full-sized) images, and for thumbnails. Let’s imagine that you want to loop through all your users’ “TN” folders and print the filenames. This would require a relatively large snippet of code if you were to use open_dir(); however, with glob(), it’s easy.
foreach(glob('userImages/*/TN/*') as $image)
{
echo "Filename: " . $image . "<br />";
}
This will search userImages/any/TN/any and will return a list of the files that match the pattern.
Filename: userImages/username1/TN/test.jpg Filename: userImages/username1/TN/test3.jpg Filename: userImages/username1/TN/test5.png Filename: userImages/username2/TN/subfolder Filename: userImages/username2/TN/test2.jpg Filename: userImages/username2/TN/test4.gif Filename: userImages/username3/TN/styles.css
We can even take things a step further, and be more specific by including a file format in our foreach statement:
XEROX CODE
foreach(glob('userImages/*/TN/*.jpg') as $image)
{
echo "Filename: " . $image . "<br />";
}
Now, this will only return Jpegs.
Filename: userImages/username1/TN/test.jpg Filename: userImages/username1/TN/test3.jpg Filename: userImages/username2/TN/test2.jpg
It gets even better. What if, for instance, you require Jpegs, but also Gifs; nothing else? Or what if you want to print only folder names? This is where the second argument comes into play.
Step 2. The Second Argument
The second argument is, as mentioned previously, optional. It does, however, provide a very nice set of optional flags. These will allow you to change the way your glob() behaves.
- GLOB_MARK: Adds a slash to each directory returned
- GLOB_NOSORT: Return files as they appear in the directory (no sorting)
- GLOB_NOCHECK: Return the search pattern if no files matching it were found
- GLOB_NOESCAPE: Backslashes do not quote metacharacters
- GLOB_BRACE: Expands {a,b,c} to match ‘a’, ‘b’, or ‘c’
- GLOB_ONLYDIR: Return only directory entries which match the pattern
- GLOB_ERR: Stop on read errors (like unreadable directories), by default errors are ignored
As you see, the potential requirements that we noted at the end of Step 1 can easily be fixed with GLOB_BRACE:
foreach(glob('userImages/*/TN/{*.jpg,*.gif}', GLOB_BRACE) as $image)
{
echo "Filename: " . $image . "<br />";
}
which will return this:
Filename: userImages/username1/TN/test.jpg Filename: userImages/username1/TN/test3.jpg Filename: userImages/username2/TN/test2.jpg Filename: userImages/username2/TN/test4.gif
If we wish to only print subfolder names, we could use GLOB_ONLYDIR:
foreach(glob('userImages/*/TN/*', GLOB_ONLYDIR) as $image)
{
echo "Filename: " . $image . "<br />";
}
which will print:
Filename: userImages/username2/TN/subfolder
Conclusion and One More Example
This method has been available since PHP 4.3, however, it’s not used very often, strangely. I didn’t learn it until quite late myself. Now, I often use glob() when loading plugins into my framework:
foreach(glob('includes/plugins/*.php') as $plugin)
{
include_once($plugin);
}
That’s all; I hope you enjoyed this quick tip, and let me know if you have any questions!








jQuery Lightbox Evolution only $12.00
Events Calendar Pro - Wordpr ... only $30.00 
Good to know such tips.
Thanks
Keep up the good work.
Tanmay
glob() is a wonderful tool, however unless you know the files will be accessible at time of writing (which is never really for sure), you should put the output of glob into a variable and check for errors before feeding it to foreach(). If glob returns an error it will return FALSE which will cause foreach to spit out a nasty error message. For example:
if ($results = glob($path))
{
foreach($results as $entry)
{
// do stuff
}
}
else
{
// handle error
}
If you use PHP 5 & OOP you can use a try() block as well:
try
{
foreach(glob($path) as $entry)
{
// do stuff
}
}
catch (Exception $e)
{
// handle error
}
And of course, needless to say, if you pass any user input to the path parameter of glob(), make sure you properly filter and validate it first!
Very helpful, Thks!
Hmm, I have never heard of this function before… I need to stop doing things the old fashioned way.
PHP is popular server programing so far, easy to develop and many server available to use. That make PHP growing very quickly…
About this functions, this is the first time I hear it
I haven’t written directory code (been using frameworks for awhile now) for so long that I was not aware of this function either (as another poster admitted.) Thanks. Certainly very useful from what I can see.
I find it a little disturbing that I see the PHP manual using a function call as the array expression inside for loops in their glob examples also. Didn’t Rasmus or another top PHP core developer explain that this is suboptimal coding practice? Or is this another area where my PHP knowledge is falling a bit behind the times?
The PHP manual page examples are intended to show, as simply and clearly as possible, the usage of the particular item being documented. Micro-optimisations are generally not at the forefront of the documentor’s mind when trying to give a concise example.
Cool~ The usage of glob() is always one of my frequent asked interview questions — please give me an easiest way to find the files with certain format(e.g. .gif/.jpg) under a given folder; mostly of the time I got a disappointing answer…
Angus – Don’t you think that those sort of questions in an interview is redundant?
Maybe it is because I am a mere mortal and am not as brilliant as you, since you know EVERY function in PHP.
A lot of programming is on the fly finding solutions. A brilliant programmer may of never needed to find files in a particular directory before. There you go asking him about some obscure function which those sort of questions are purely to make yourself feel elitist rather than test the ability of the programmer. You would be much better off finding out how he would approach the task rather then the final solution.
So I hope you feel good in your ivory tower making people feel crap when they are already nervous in an interview because they do not know about one little PHP function which is one of the lesser known functions.
Seriously you are the type that gives web developers a bad reputation.
Dale
Thanks for this
Haven’t heard of it either!
Can you tell me something about performance? Especially in comparison with PHP’s DirectoryIterator? Thx
Regards,
Daigo
It’s my favorite function, I was always using it but I was missing (Step 2)
Thanks, That’s really helped me.
Well this function would of saved me a lot of time when I was building an FTP photo library a few weeks back! Really well explained, nice work.
Ouh, that’s why i don’t call me a pro. Thank you for broadening my horizon.
Great Tutorail. I will add this in my memory when ever have to use Directories in PHP.
Wow. I had never heard of this function before. This article is definitely going to be sitting in my developer bookmarks for while until I have mastered it. Fantastic!
The functions glob is really powerful and cool. I was always using opendir() to get files in some folder, and I had to check if the current file is (.) or (..). It’s bored. I like the wildcard chars in glob function, it helps to reduce checking curtain files. Thanks for the post.
That is really helpful when reading a contents of a folder.
Very cool. Thanks.
Thanks for pointing this out. I’ve never seen it before and I will definitely find use for it.
glob() is convenient, but it can be several times *slower* than using readdir(). At least you should use GLOB_NOSORT if you don’t care about the order. This mitigates the performance cost a lot.
This came up on Stack Overflow in January. I benchmarked several methods that other users suggested for reading a directory. My code and the results is here:
http://stackoverflow.com/questions/2120287/directory-to-array-with-php/2120496#2120496
The results ranged from 12.4 seconds down to 1.2 seconds. That’s a pretty wide spread, so it’s worth paying attention to performance as well as coding convenience.
Looping through folders without SPL is criminal….
http://www.php.net/manual/en/recursivedirectoryiterator.construct.php
Very helpful, but I found that opendir is a little bit faster than glob
I put the following script
<?php
$dir = "pics/sports/b/";
if($handle = opendir($dir)) {
while($file = readdir($handle)) {
clearstatcache();
if(is_file($dir.'/'.$file))
echo '‘;
}
closedir($handle);
}
?>
in a page and it worked faster than glob
Looks very cool. I am used to using opendir/readdir. I am curious, though: is it possible to search for all ,jpg images, like you have, except leave off any images with say *_tn.jpg? This would be awesome if it were possible without having to explode the filename.
5 years ago this was a great tip, before PHP 5 became the de-facto and PHP 4 a rarity only found on ancient servers.
These days PHP has a built in function to facilitate this, its called scandir(). Over a thousand iterations of looping through a directory, the times were:
glob(dir/*) – 0.13954
scandir(dir) – 0.06261
Note that scandir is more than twice as fast, and avoids the need for unintuitive wildcards.
Also note that setting scandir results into a variable first, as someone suggested for the glob(), offers no change, it would be premature optimization, unless thats just how you like to do it.
I actually like it.
foreach(glob(‘libraries/*.js’) as $js){
echo ”;
}
And you can do the same thing for stylesheets.
Wow, this little method saved me lines of code. Thank you!
Say goodbye to readir() and say hello to glob() =D !!!
Excellent, a time saver, thanks!