Back to Blog
A
PHP Architect ·

Putting glob() to the test

In a new NetTuts+ post, Marcus Schumann offers a quick tip: Loop Through Folders with PHP’s Glob().
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.
The glob() function is convenient but the solution using the fewest lines of code isn't always the most efficient -- if by efficient you mean fastest. This came up in a question on Stack Overflow in January.  A user asked how best to get a list of files in a directory (excluding "." and ".." and other subdirectories) and return it as an array.  Several readers offered suggestions, and out of curiosity I benchmarked all their alternatives.  I ran each method 1,000 times on a directory containing about 400 files.  My benchmark 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. Here are the results in order from slowest to fastest method: The first method was to use glob() to return an array, and then loop over the result to exclude directories.  This was the slowest, running in 12.4 seconds.
    foreach(glob('*') as $file_or_dir) {
        if( !is_dir($file_or_dir) ) // is_dir will match . and ..
        {
            $files[] = $file_or_dir;
        }
    }
Next was simply using glob() without filtering directories. This ran in 8.1 seconds.
    $files = glob('*');
Using glob() with the optional GLOB_NOSORT argument shows how much impact sorting has on the results. If you don't need sorted results, it's worthwhile to say so, because this solution ran in 6.4 seconds -- nearly double the performance of the slowest method.
    foreach(glob('*', GLOB_NOSORT) as $file_or_dir) {
        if( !is_dir($file_or_dir) ) // is_dir will match . and ..
        {
            $files[] = $file_or_dir;
        }
    }
The scandir() function is another alternative.  This ran in 6.5 seconds.
    $files = scandir('.');
    $result = array();
    foreach ($files as $file)
    {
        if (($file == '.') || ($file == '..'))
        {
            continue;
        }
        $result[] = $file;
    }
Next using scandir() with array_diff() to filter out the dot-directories had slightly better performance at 6.4 seconds, and this is almost as concise as using glob().
    $files = array_diff(scandir('.'), array('.', '..'));
The opendir() method for which Marcus wanted to find an alternative isn't so shabby. This ran in 5.3 seconds.
    $files = array();
    $dir = opendir('.');
    while(($currentfile = readdir($dir)) !== false)
    {
        if( !is_dir($currentfile) )
        {
            $files[] = $currentfile;
        }
    }
    closedir($dir);
But using glob() in a bare form with GLOB_NOSORT shows that it may have been pretty costly to loop over the results.  This ran in 2.2 seconds.
    $files = glob('*', GLOB_NOSORT);
Or perhaps is_dir() was the source of the performance problem, because if we use opendir() and filter results by comparing to literal dot-directory names, we get the time down to 1.2 seconds.
    $files = array();
    $dir = opendir('.');
    while(($currentFile = readdir($dir)) !== false)
    {
        if ( $currentFile == '.' or $currentFile == '..' )
        {
            continue;
        }
        $files[] = $currentFile;
    }
    closedir($dir);
Of course it's desirable to write concise code, but don't assume this always equates to fast code. Rapid development and rapid code are independent goals, and you need to decide which has greater priority on a case-by-case basis. And remember to use GLOB_NOSORT unless you actually need the list of files sorted. Photo courtesy of Rick Audet. http://www.flickr.com/photos/spine/2425394931/ Released under Creative Commons Attribution licenses.
A

PHP Architect

April 28, 2010

Share

Our Partners

Collaborating with industry leaders to bring you the best PHP resources and expertise

Interested in partnering? Get in touch →