Skip to content
Advertisement

Get latest file in dir including subdirectory php

i found out that i can use

$files = scandir('c:myfolder', SCANDIR_SORT_DESCENDING);
$newest_file = $files[0];

to get the latest file in the given directory (‘myfolder’). is there an easy way to get the latest file including subdirectorys?

like:

myfolder> dir1 > file_older1.txt

myfolder> dir2 > dir3 > newest_file_in_maindir.txt

myfolder> dir4 > file_older2.txt

Thanks in advance

Advertisement

Answer

To the best of my knowledge, you have to recursively check every folder and file to get the last modified file. And you’re current solution doesn’t check the last modified file but sorts the files in descending order by name.

Meaning if you have a 10 years old file named z.txt it will probably end up on top.

I’ve cooked up a solution.

  1. The function accepts a directory name and makes sure the directory exists. It returns null when the directory has no files or any of its subdirectories.
  2. Sets aside the variables $latest and $latestTime where the last modified file is stored.
  3. It loops through the directory, avoiding the . and .. since they can cause an infinite recursion loop.
  4. In the loop the full filename is assembled from the initial directory name and the part.
  5. The filename is checked if it is a directory if so it calls the same function we are in and saves the result.
  6. If the result is null we continue the loop otherwise we save the file as the new filename, which we now know is a file.
  7. After that we check the last modified time using filemtime and see if the $latestTime is smaller meaning the file was modified earlier in time that the current one.
  8. If the new file is indeed younger we save the new values to $latest and $latestTime where $latest is the filename.
  9. When the loop finishes we return the result.
function find_last_modified_file(string $dir): ?string
{
    if (!is_dir($dir)) throw new ValueError('Expecting a valid directory!');

    $latest = null;
    $latestTime = 0;
    foreach (scandir($dir) as $path) if (!in_array($path, ['.', '..'], true)) {
        $filename = $dir . DIRECTORY_SEPARATOR . $path;

        if (is_dir($filename)) {
            $directoryLastModifiedFile = find_last_modified_file($filename);

            if (null === $directoryLastModifiedFile) {
                continue;
            } else {
                $filename = $directoryLastModifiedFile;
            }
        }

        $lastModified = filemtime($filename);
        if ($lastModified > $latestTime) {
            $latestTime = $lastModified;
            $latest = $filename;
        }
    }

    return $latest;
}

echo find_last_modified_file(__DIR__);

In step 7 there is an edge case if both files were modified at the exact same time this is up to you how you want to solve. I’ve opted to leaving the initial file with that modified time instead of updating it.

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement