Issue
I've got this function to get files from a directory on an SFTP. It returns all files in the folder, but with a filetime that is hard to parse.
What I want is to get the latest modified file.
private function getDirList()
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this -> host);
curl_setopt($ch, CURLOPT_USERPWD, $this -> user . ":" . $this -> pass);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
if (curl_exec($ch) === false) {
echo 'Curl error: ' . curl_error($ch);
exit();
}
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'LIST');
$result = trim(curl_exec($ch));
$files = array();
foreach (explode("\n", trim($result, "\n")) as $line) {
$files[] = $line;
}
return $files;
}
What I get from the function:
Array
(
[0] => -rw-rw-rw- 1 user group 4482926 Jan 19 01:30 file1.csv
[1] => -rw-rw-rw- 1 user group 4291169 Oct 21 00:33 file2.csv
[2] => -rw-rw-rw- 1 user group 4469721 Dec 14 01:30 file3.csv
[3] => -rw-rw-rw- 1 user group 4275439 Sep 28 00:30 file4.csv
[4] => -rw-rw-rw- 1 user group 4244881 Sep 6 2018 file5.csv
[5] => -rw-rw-rw- 1 user group 4310557 Nov 2 01:30 file6.csv
[6] => -rw-rw-rw- 1 user group 4310765 Nov 5 01:30 file7.csv
[7] => -rw-rw-rw- 1 user group 4245407 Sep 11 00:30 file8.csv
[8] => -rw-rw-rw- 1 user group 4198017 Sep 1 2018 file9.csv
[9] => -rw-rw-rw- 1 user group 4311228 Nov 10 01:31 file10.csv
...
Could I do a call for each file and get a better filetime? Could I send a different customrequest for a different listing?
Solution
Consider using phpseclib.
With it, you can use the following code:
$sftp = new phpseclib\Net\SFTP($hostname);
$sftp->login($username, $password) or die("Cannot login");
$files = $sftp->rawlist($path);
// filter out folders
$files_only_callback = function($a) { return ($a["type"] == NET_SFTP_TYPE_REGULAR); };
$files = array_filter($files, $files_only_callback);
// sort by timestamp
usort($files, function($a, $b) { return $b["mtime"] - $a["mtime"]; });
// In PHP 7, you can use spaceship operator instead:
// usort($files, function($a, $b) { return $a["mtime"] <=> $b["mtime"]; });
// pick the latest file
$latest = $files[0]["filename"];
phpseclib does not need any installation. Just extract the source code package along with your code. Though to load the latest phpseclib 2.0, they recommend using Composer. If you do not want to rely on yet another library for loading, you can use the following code to load phpseclib:
spl_autoload_register(function ($class) {
$file = stream_resolve_include_path(
str_replace('\\', DIRECTORY_SEPARATOR, $class).'.php');
if ($file !== false) {
require $file;
return true;
}
return false;
});
$phpseclib_path = "phpseclib";
set_include_path(get_include_path() . PATH_SEPARATOR . $phpseclib_path);
(based on Test whether a file exists anywhere in the include path)
Answered By - Martin Prikryl Answer Checked By - Clifford M. (WPSolving Volunteer)