Try Tuts+ Premium, Get Cash Back!
Quick Tip: Loop Through Folders with PHP’s Glob()

Quick Tip: Loop Through Folders with PHP’s Glob()

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:

	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!

Tags: tips
Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • tanmay joshi

    Good to know such tips.

    Thanks
    Keep up the good work.

    Tanmay

  • http://www.nine10.ca/ Richard Podsada

    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! :)

  • http://smokintops.com Matthieu

    Very helpful, Thks!

  • http://spotdex.com Davidmoreen

    Hmm, I have never heard of this function before… I need to stop doing things the old fashioned way.

  • http://wptricks.net WP Tricks

    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 :)

  • Bretticus

    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?

    • Peter

      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.

  • http://adfeed.cn Angus Li

    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…

    • http://createmy.com.au Dale Hurley

      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

  • Daigo

    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

  • Mohamed Zahran

    It’s my favorite function, I was always using it but I was missing (Step 2)
    Thanks, That’s really helped me.

  • http://www.nouveller.com/ Benjamin Reid

    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.

  • Patrick

    Ouh, that’s why i don’t call me a pro. Thank you for broadening my horizon.

  • http://www.artologics.com Shopping Cart

    Great Tutorail. I will add this in my memory when ever have to use Directories in PHP.

  • http://matt-bridges.com Matt Bridges

    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!

  • http://www.deluxeblogtips.com Deluxe Blog Tips

    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.

  • http://www.jordanwalker.net Jordan Walker

    That is really helpful when reading a contents of a folder.

  • http://www.madeofwin.de Ben

    Very cool. Thanks.

  • http://www.aaronharp.com Aaron

    Thanks for pointing this out. I’ve never seen it before and I will definitely find use for it.

  • http://karwin.blogspot.com Bill Karwin

    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.

  • idont

    Looping through folders without SPL is criminal…. ;)

    http://www.php.net/manual/en/recursivedirectoryiterator.construct.php

  • http:/www.wise.gr Giorgos

    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

    • http://www.phpmysqlfreelancer.com/ Juli

      threre is not any speed concern with both – we can avoid extra lines in the coidng needed for opendir()

  • http://ryanreed.net Ryan Reed

    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.

  • Kevin Dean

    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.

  • http://blog.jackbliss.co.uk Jack Bliss

    I actually like it.

    foreach(glob(‘libraries/*.js’) as $js){
    echo ”;
    }

    And you can do the same thing for stylesheets.

  • http://www.bionicworks.com Thai

    Wow, this little method saved me lines of code. Thank you!

  • a77icu5

    Say goodbye to readir() and say hello to glob() =D !!!

  • http://www.fishmemory.net fractalbit

    Excellent, a time saver, thanks!

  • quang trung

    How to scan folder which name is unicode like this dir\olá
    Sample with case file have a unicode name ă.jpg

  • Piyush Rahate

    That was real time saver quick tip. I was used to “opendir” and didn’t ever realized that glob will make life so easy.

    @Bill, thanks to you as well for the comparison provided.

    @Kevin, will check scandir :)

  • ollly

    Thank you! Great tutorial.

  • http://www.e-sushi.net/ Mike Edward Moras (e-sushi™)

    You should’ve also pointed out that OpenDir is PHP native and portable while glob is system dependent. e.g.: it will not work on Sun Solaris and some unix and linux systems.

    My 2 cents to readers: keep it portable and avoid system dependencies.

    My 2 cents to the writer: tell the complete story or you’ll make a fool out of yourself by confusing learning users. Think about how many of them wonder why opendir exists at all after reading your… “post”.

    • dbind

      @Mike Edward Moras (e-sushi™), did you happen to think that maybe he didn’t know that? This is not a PHP Core developer writing, so he might ignore a few things about PHP. Yeah, normal people tend to not know stuff, not like you. Next time you could try a constructive aproach like “I found out this and that, should you want to know”. See how less full-of-yourself you could sound?

      Now my two cents: I’ve had problems with glob correctly listing paths with ‘[' and ']‘ in them. Couldn’t find a good workaround in the net yet, so I’m sticking to scandir for this task. Great article anyway, thank you!

      • dbind

        Got it! You escape special chars by putting them between square brackets, like this:

        [ becomes [[]
        ] becomes []]

        …and so on.

        Might work with non-ascii chars (someone mentioned them above), haven’t tried.

      • http://www.e-sushi.net/ Mike Edward Moras (e-sushi™)

        @dbind

        I’m so glad you’re not a troll but a specialist finding my comment 3 months later and missing the point that my critique went against the article writer.

        Especially when he’s “not a PHP Core developer writing, so he might ignore a few things about PHP”, he should try to do his research instead of posting incomplete information.

        And related to your problems: you could have asked; or at least taken my comment as a good hint related to portability… and if everything would have failed you could have simply acknowledged that my comment gave you the solution to your problem: use OpenDir.

        But you were too busy preparing a rant to see that, weren’t you?

      • http://www.e-sushi.net/ Mike Edward Moras (e-sushi™)

        Let me add that the example used in “Conclusion and One More Example” and the code shown is actually a great example of a security issue waiting to be exploited.

        Why?

        The used code would include EVERY php file. Look at it twice:

        foreach(glob(‘includes/plugins/*.php’) as $plugin)

        Why not try “unlink *.*” too instead of waiting for the exploit to happen? ;)

      • Tanax

        @Mike- You seem like a friendly guy. Hmm. In any case, please explain what you mean with “exploit to happen”?

  • Steven

    Nice tut, thanks. Though that last snippet of code looks pretty dangerous >

    foreach(glob(‘includes/plugins/*.php’) as $plugin)
    {
    include_once($plugin);
    }

    If a user with bad intentions manages to get access to your ftp and just pastes one of his own malicious “plugin” files in that folder it will automatically be included in your site.

    • Tanax

      If a user gains access to your FTP, they can do pretty much whatever they want anyway.

      • http://e-sushi.net Mike Edward Moras (e-sushi™)

        Well, there are other ways a server might get compromised. Ever heard of executable PHP in images? Or the woes of fighting MySQL injections? Or website admin areas being accessed after a simple upload injection? Oh, and I remember hordes of WordPress users crying about their plugins (eg: the “TimThumb.php” problems). Google about it… it’s a practical eye-opener once you read what was the cause of the issue.

        To keep it short: there’s more out there than just having your FTP hacked. Most of the time, you will find FTP not being the weakest point when your website goes down the drain. That’s why it’s so important to spread “secure” tutorials, not “something whipped up blindly”… #JustSaying

  • Keith

    Hi,

    Was wondering if the output can be alphabetically sorted, inclusive of lower and uppercase.

    Thanks in advance

  • Eliud

    Loved it, although…

    What if I want to search for a only subdirectories AND certain file types.

    Ex. I have a folder named “stuff” where random stuff is uploaded. And say I want to search for just subfolders AND .jpg files within “stuff” and nothing more. I know to search for only .jpg is…

    $array = glob(‘stuff/{*.jpg}’, GLOB_BRACE);

    and to search for only subdirectories is…

    $array = glob(‘stuff/*’, GLOB_ONLYDIR);

    …but how do I combine the two? Is there a pattern for subirectories for GLOB_BRACE?

  • http://www.ehomebusinessopportunities.com/ click here

    Greetings! I’ve been reading your weblog for a long time now and finally got the courage to go ahead and give you a shout out from Austin Texas! Just wanted to tell you keep up the good job!

  • http://e-sushi.net/ Mike Edward Moras (e-sushi™)

    If speed is something worth to you, you’ll not want to use a shell-command like GLOB at all!!!

    I happened to find hxxp://www.phparch.com/2010/04/putting-glob-to-the-test/ with a nice re-take on this “tutorial”.

    • Windo

      Hi Mike, just curious to know more about this. Can you explain more ? Thanks !

  • rituraj

    Good one by this now can write some short code