Using glob() to iterate through directories

December 10, 2016 WordPress PHP

Ever want to go through folders on a project to either include files or just list them out for a user? Have you tried to use glob?

Just like the PHP docs say, the glob() function searches for all the pathnames matching pattern according to the rules used by the libc glob() function, which is similar to the rules used by common shells.

WordPress install directory list with globs.php

Although that may be a bit cryptic sounding, it's pretty easy to use. In this quick tutorial, we're going to create a function that pulls a list of files from any project. Just for testing purposes, we're going to include our script in the root directory of a WordPress install (only because it's open source and it already comes with a lot of files and directories).

To make it clear, this file does nothing to WordPress. However, you can use it with a WordPress theme or plugin, I have! It comes in handy when you have to include a ton of files or autoload files into a theme'sfunctions.php file.

The completed code

Here's what we're going to create. At the end of this article, we're going to make it more compact, but for this tutorial's purposes, we're going to keep it broken up.

/**
 * Returns an array of directory paths
 * @param string $path
 * @return array
 */
function getFileList($path = '') {
    // Check for empty, return an empty array or this can be changed to
    // return false
    if(empty($path)) {
        return [];
    }

    // Grab all files under the path provided regardless of extension
    $dirs = glob($path . '/*');

    // Filter everything that isn't a directory using is_dir()
    $dirs = array_map(function($dir) {
        return is_dir($dir) ? $dir : false;
    }, $dirs);

    // Remove all items set as false
    $dirs = array_filter($dirs);

    // Reset the keys of the array, removing the previous false
    // values made our array's keys `wonky`
    $dirs = array_values($dirs);

    // Return the list
    return $dirs;
}

// This will call our function and display a list of files
$dirs = getFileList( __DIR__ . '/wp-admin' );

Using a var_dump( $dirs ) this is what we see. (The backlashes vs forward slashes are there because I'm on a PC using WAMP)

array (size=7)
  0 => string 'C:\wamp\www\wordpress2\wwwroot/wp-admin/css' (length=43)
  1 => string 'C:\wamp\www\wordpress2\wwwroot/wp-admin/images' (length=46)
  2 => string 'C:\wamp\www\wordpress2\wwwroot/wp-admin/includes' (length=48)
  3 => string 'C:\wamp\www\wordpress2\wwwroot/wp-admin/js' (length=42)
  4 => string 'C:\wamp\www\wordpress2\wwwroot/wp-admin/maint' (length=45)
  5 => string 'C:\wamp\www\wordpress2\wwwroot/wp-admin/network' (length=47)
  6 => string 'C:\wamp\www\wordpress2\wwwroot/wp-admin/user' (length=44)

Hopefully you can see how useful this can be when you have to load a bunch of files from a list of directories. That being said, the function can be reworked to include php files as well.

Lets break it down

First we grab all files using the asterisk as the wildcard pattern indicator on the__DIR__ . '/wp-admin/*' path. We use the __DIR__ magic constant here to return the current directory our file lives in. In this case, for my setup, it's c:\wamp\www\wordpress2\wwwroot. Because this is a WordPress install, we can then point it to the wp-admin directory for it to walk through the directories that.

$dirs = glob(__DIR__ . '/wp-admin/*');

This then outputs a giant list of files (85 to be exact). We don't need all of these files, remember we're only looking for directories for this exercise. Here's where we use array_map with a closure to remove everything that is not a directory.

$dirs = glob(__DIR__ . '/wp-admin/*');

$dirs = array_map(function($dir) {
    return is_dir($dir) ? $dir : false;
}, $dirs);

Now if we print this out, we still get the same amount of items, however you will notice that everything that was once a file (like a .php or .txt file) is now false. This is going to make it super easy to filter out since PHP comes with a handy function: array_filter( ).

$dirs = glob(__DIR__ . '/wp-admin/*');

$dirs = array_map(function($dir) {
    return is_dir($dir) ? $dir : false;
}, $dirs);

$dirs = array_filter($dirs);

Here's what we see now:

array (size=7)
  10 => string 'C:\wamp\www\wordpress2\wwwroot/wp-admin/css' (length=43)
  23 => string 'C:\wamp\www\wordpress2\wwwroot/wp-admin/images' (length=46)
  25 => string 'C:\wamp\www\wordpress2\wwwroot/wp-admin/includes' (length=48)
  29 => string 'C:\wamp\www\wordpress2\wwwroot/wp-admin/js' (length=42)
  36 => string 'C:\wamp\www\wordpress2\wwwroot/wp-admin/maint' (length=45)
  53 => string 'C:\wamp\www\wordpress2\wwwroot/wp-admin/network' (length=47)
  82 => string 'C:\wamp\www\wordpress2\wwwroot/wp-admin/user' (length=44)

It's pretty much done..

The above code will work, and you can iterate through them easily, all the code above can also be placed in a function and resused. But if you're like me, you'll probably want to reset those wonky array keys back to the 0 index.

We can use array_values for this as it returns the values of the array that is passed to it, but it resets all indexes back to 0.

function getFIleList($path = '' ) {
    $dirs = glob($path . '/*');

    $dirs = array_map(function($dir) {
        return is_dir($dir) ? $dir : false;
    }, $dirs);

    $dirs = array_filter($dirs);

    $dirs = array_values($dirs);

    return $dirs;
}

getFileList(__DIR__ . '/wp-admin');

Now we get a clean array with pretty index keys.

array (size=7)
  0 => string 'C:\wamp\www\wordpress2\wwwroot/wp-admin/css' (length=43)
  1 => string 'C:\wamp\www\wordpress2\wwwroot/wp-admin/images' (length=46)
  2 => string 'C:\wamp\www\wordpress2\wwwroot/wp-admin/includes' (length=48)
  3 => string 'C:\wamp\www\wordpress2\wwwroot/wp-admin/js' (length=42)
  4 => string 'C:\wamp\www\wordpress2\wwwroot/wp-admin/maint' (length=45)
  5 => string 'C:\wamp\www\wordpress2\wwwroot/wp-admin/network' (length=47)
  6 => string 'C:\wamp\www\wordpress2\wwwroot/wp-admin/user' (length=44)

Lets make it compact!

Not everything needs to be placed in a variable, it does make it easy to read and work with, but we don't need it. Lets compact the function by removing its variables.

function getFileList($path = '') {
    return array_values(array_filter(array_map(function($dir) {
        return is_dir($dir) ? $dir : false;
    }, glob($path . '/*'))));
}