How to get the newest file in a directory in php

Viewed 61817

So I have this app that processes CSV files. I have a line of code to load the file.

$myFile = "data/FrontlineSMS_Message_Export_20120721.csv";  //The name of the CSV file
$fh = fopen($myFile, 'r');                             //Open the file

I would like to find a way in which I could look in the data directory and get the newest file (they all have date tags so they would be in order inside of data) and set the name equal to $myFile.

I really couldn't find and understand the documentation of php directories so any helpful resources would be appreciated as well. Thank you.

4 Answers

For a search with wildcard you can use:

<?php
$path = "/var/www/html/*";

$latest_ctime = 0;
$latest_filename = '';

$files = glob($path);
foreach($files as $file)
{
        if (is_file($file) && filectime($file) > $latest_ctime)
        {
                $latest_ctime = filectime($file);
                $latest_filename = $file;
        }
}
return $latest_filename;
?>

My solution, improved solution from Max Hofmann:

$ret = [];
$dir = Yii::getAlias("@app") . "/web/uploads/problem-letters/{$this->id}"; // set directory in question

if(is_dir($dir)) {
   $ret = array_diff(scandir($dir), array(".", "..")); // get all files in dir as array and remove . and .. from it
}

usort($ret, function ($a, $b) use ($dir) {
    if(filectime($dir . "/" . $a) < filectime($dir . "/" . $b)) {
         return -1;
    } else if(filectime($dir . "/" . $a) == filectime($dir . "/" . $b)) {
         return 0;
    } else {
         return 1;
    }
}); // sort array by file creation time, older first

echo $ret[count($ret)-1]; // filename of last created file

Here's an example where I felt more confident in using my own validator rather than simply relying on a timestamp with scandir().

In this context, I want to check if my server has a more recent file version than the client's version. So I compare version numbers from the file names.

$clientAppVersion = "1.0.5";
$latestVersionFileName = "";

$directory = "../../download/updates/darwin/"
$arrayOfFiles = scandir($directory);
foreach ($arrayOfFiles as $file) {
    if (is_file($directory . $file)) {
        // Your custom code here... For example:
        $serverFileVersion = getVersionNumberFromFileName($file);
        if (isVersionNumberGreater($serverFileVersion, $clientAppVersion)) {
            $latestVersionFileName = $file;
        }
    }
}


// function declarations in my php file (used in the forEach loop)
function getVersionNumberFromFileName($fileName) {
    // extract the version number with regEx replacement
    return preg_replace("/Finance D - Tenue de livres-darwin-(x64|arm64)-|\.zip/", "", $fileName);
}

function removeAllNonDigits($semanticVersionString) {
    // use regex replacement to keep only numeric values in the semantic version string
    return preg_replace("/\D+/", "", $semanticVersionString);
}

function isVersionNumberGreater($serverFileVersion, $clientFileVersion): bool {
    // receives two semantic versions (1.0.4) and compares their numeric value (104)
    // true when server version is greater than client version (105 > 104)
    return removeAllNonDigits($serverFileVersion) > removeAllNonDigits($clientFileVersion);
}

Using this manual comparison instead of a timestamp I can achieve a more surgical result. I hope this can give you some useful ideas if you have a similar requirement.

(PS: I took time to post because I was not satisfied with the answers I found relating to the specific requirement I had. Please be kind I'm also not very used to StackOverflow - Thanks!)

Related