(new Soapbox())->shout(array_map('strtoupper', $opinions)); //Shaun's blog

Me, elsewhere

Miscellaneous public code

A PHP API client for Reddit

I don't tweet much

XMPP chat
(Pidgin, Miranda, Swift, etc.)

Perfect is the enemy of good enough.

Getting directory contents by date in PHP

Posted April 15, 2017 by shaun

When working with directory contents, sometimes it's useful to list the files by age, either newest or oldest first. For example, you might want to display the 10 most recently uploaded photos in a directory, or delete the oldest files from a temp directory. PHP provides an easy way to get a directory's file listing, scandir(), but it sorts the file list alphabetically. What if you'd rather sort by date?

To build a date-ordered file list, it's necessary to read the directory contents manually with opendir() and readdir(). As each file is discovered, it can be added to an array using its modification time as the array key. Finally, the resulting array can be sorted (or reverse-sorted) by key, producing a list of files that's ordered by date, from oldest to newest (or vice versa).

Here's a function, scandir_chrono(), that implements this logic with a few extra features:

 * Return an array of file paths representing the contents of the target
 * directory, ordered by date instead of by filename.
 * @param string $path The target directory path
 * @param bool $reverse Whether to sort in reverse date order (oldest first)
 * @param array $exts If set, only find files with these extensions
 * @return array A sorted array of absolute filesystem paths
function scandir_chrono(string $path, bool $reverse = false, ?array $exts = []): array {

    /* Fail if the directory can't be opened */
    if (!(is_dir($path) && $dir = opendir($path))) {
        return [];

    /* An array to hold the results */
    $files = [];

    while (($file = readdir($dir)) !== false) {
        /* Skip anything that's not a regular file */
        if (filetype($path . '/' . $file) !== 'file') {
        /* If extensions were provided and this file doesn't match, skip it */
        if (!empty($exts) && !in_array(pathinfo($path . '/' . $file,
                                PATHINFO_EXTENSION), $exts)) {
        /* Add this file to the array with its modification time as the key */
        $files[filemtime($path . '/' . $file)] = $file;

    /* Sort and return the array */
    $fn = $reverse ? 'krsort' : 'ksort';
    return $files;

This function takes a directory path and returns an array of absolute, fully-qualified paths to each file. By default, the files are sorted from oldest to newest; to sort in the opposite direction, pass true for the $reverse parameter. Optionally, you can specify an array of file extensions you're interested in, and the returned array will only contain matching files.

For example, to get a list of all files in /tmp ordered newest first:

$files = scandir_chrono('/tmp', true);

To get a list of only txt and log files in the temp directory, sorted with the oldest files first:

$files = scandir_chrono('/tmp', false, ['txt', 'log']);

When specifying extensions, note that the dot shouldn't be included.

Recent articles

📰 Caveat with Vantec SATA/IDE to USB 2.0 Adapter and Macrium software

📰 Jay Niffley, Man of Mystery

📰 Compiling Doxygen on FreeBSD without LaTeX and Ghostscript

📰 Introducing Snuze, a PHP client for the Reddit API

📰 jisusaiche: Java's installer telemetry

📰 BIND client log error "query_find: query_getdb failed"

📰 Resolving "The lang/perl5.24 port has been deleted: Has expired" portmaster error

📰 Armagaddon2 interim fix for Firefox 56 and other old versions

📰 Strange DNS queries: qname "miep", qtype ANY

📰 Undeliverable as addressed: A massive broken spam campaign?

📰 Using WITH_META_MODE and ccache for FreeBSD build boosts

📰 Resolving subversion error E000013: Unable to create pristine install stream

📰 Enhancements to SmokePing's AnotherDNS probe

📰 Generating vanity DNSSEC key tags

📰 DDoS involving forged packets from

▲ Back to top | Permalink to this page