How get first modified file?
So far I've had:
$dir = $path.'/';
$firstMod = '';
$p = 1;
foreach (scandir($dir) as $file) {
if (is_file($dir.$file) && ... ) {
if($p == 1) break;
}
}
If I would like to get last file but not last modified but last in an folder order what should I use?
you can try to write all the files in the array make key as the date modified than reorder the array based on date and get the first element of array which would first modified.
<?php
$folder = "files/";
$handle = opendir($folder);
$files=array();
while ($file = readdir($handle)){
if( $file != ".." && $file != "." ){
$key = filemtime($file);
$files[$key] = $file ;
}
}
closedir($handle);
ksort($files) ;
echo reset($files);
?>
Related
I would appreciate if I can ask a question about php.
In my website, I will use a file "timestamp.php" under public_html to display the time between updating files in directory "public_html."
$dir = dir($directory); // get directory handler
while(($file = $dir->read()) !== false) { // read the directory in loop
if($file == '..') continue; // this is the parent folder
if($file == '.') continue; // this is the current folder // this is the php file
Let me call this website as a 'formal site'.
Now I want to create a 'development site' but sharing the same time counter: that is, updating the 'development_site' will also update a counter displayed at the formal site.
I set up the 'development site' at public_html/development_site. (I am not sure whether this is the best place to put a 'development_site,' but as a starter)
But at this moment updating files in public_html does update the counter, but updating files in public_html/development_site will not update the counter.
Thus I need to set timestamp.php to look for files in public_html/development_site. I like to know how to modify timestamp.php to check files in public_html/development_site.
I have tried
$directory= "/nfs/.../public_html";
$devdirectory="/nfs/.../public_html/development_site";
$dir = dir($directory); // get directory handler
$dir2=dir($devdirectory);//
while((($file = $dir2->read()) !== false)|| (($file = $dir->read()) !== false))
{ // read the directory in loop
if($file == '..') continue; // this is the parent folder
if($file == '.') continue; // this is the current folder // this is the php file
But it does not update counter when a file is updated in development directory. I will appreciate comments.
Here is the entire code.
<?php
$stats_array = array();
$counter = 1;
$directory = "/nfs/.../public_html";
$devdirectory = "/nfs/.../public_html/dev";
if(is_file('/nfs/.../filestat.txt')) {
$file_array = file('/nfs/.../filestat.txt');
foreach($file_array as $line) {
// tab delimited timestamp, filename, counter
$line = trim($line);
if(!empty($line)) {
$line_array = explode("\t",$line);
$stats_array[md5($line_array[1])] = $line_array;
}
}
}
$files = array(); // create empty array
$dir = dir($directory); // get directory handler
$dir2 = dir($devdirectory); // get directory handler
while(($file = $dir->read()) !== false) { // read the directory in loop
if($file == '..') continue; // this is the parent folder
if($file == '.') continue; // this is the current folder // this is the php file
if(strpos($file, '.jpg') !== false) continue;
if(strpos($file, '.jpeg') !== false) continue;
if(strpos($file, '.xml') !== false) continue;
if(strpos($file, '.gif') !== false) continue;
if(strpos($file, '.png') !== false) continue;
if(strpos($file, '.png') !== false) continue;
if(strpos($file, '.html') == false) continue; // this is the html file
if($file == '.htaccess') continue; // this is the security file
if($file == 'filestat.txt') continue; // this is the stats file
$file = $directory . '/' . $file;
if(is_dir($file)) continue; // this is the folder
if(!file_exists($file)) continue;
$fileinfo = new SplFileInfo($file); // get file info object
// put the file info into an array with UNIXTIME key.
$files[$fileinfo->getMTime()] = array('name'=>$file,'mtime'=>date('Y:m:d:H:i:s', $fileinfo->getMTime()),'unixtime'=>$fileinfo->getMTime());
$key = md5($file);
if(array_key_exists($key, $stats_array)) {
if($stats_array[$key][0] != date('Y:m:d:H:i:s', $fileinfo->getMTime())) {
$stats_array[$key][2]++;
$stats_array[$key][0] = date('Y:m:d:H:i:s', $fileinfo->getMTime());
}
} else {
$stats_array[$key] = array(
date('Y:m:d:H:i:s', $fileinfo->getMTime()),
$file,
1
);
}
$datetime = new \DateTime();
$datetime->setTimestamp($fileinfo->getMTime());
$files[$fileinfo->getMTime()]['age'] = $datetime->diff(new \DateTime())->format('%H:%I:%S');
if($datetime->diff(new \DateTime())->format('%a') != '0')
{
$days = ($datetime->diff(new \DateTime())->format('%a') == '1') ? ' day ' : ' days ';
$files[$fileinfo->getMTime()]['age'] = $datetime->diff(new \DateTime())->format('%a') . $days . $files[$fileinfo->getMTime()]['age'];
}
}
$dir->close(); // close the handler
ksort($files); // sort array by keys in ascending order
$newest_file = array_pop($files); //extract latest file from array
foreach($stats_array as $stat) {
$counter += $stat[2];
}
printf(
"Counter %s. (%s) Time Since the Last upload: <span class='update_time' mtime='%s'>%s</span>.",
$counter,
$newest_file['mtime'],
$newest_file['unixtime'],
$newest_file['age']// this is formatted date and time string
);
$put = '';
foreach($stats_array as $line) {
$put .= implode("\t",$line)."\n";
}
file_put_contents('/nfs/.../filestat.txt',$put);
?>
This is the complete solution that works for me, tested in debugging environment with php v7.3.19-1~deb10u1:
<?php
/*-----
CONFIG
------*/
$filestat_path = "/nfs/.../filestat.txt";
$directory = "/nfs/.../public_html";
$devdirectory = "/nfs/.../public_html/dev";
/*-----*/
$stats_array = array();
$counter = 1;
if(is_file($filestat_path)) {
$file_array = file($filestat_path);
foreach($file_array as $line) {
// tab delimited timestamp, filename, counter
$line = trim($line);
if(!empty($line)) {
$line_array = explode("\t",$line);
$stats_array[md5($line_array[1])] = $line_array;
}
}
}
$files = array(); // create empty array
$dir1 = dir($directory); // get directory handler
$dir2 = dir($devdirectory); // get directory handler
$switch = true; //we change this to false as we want to switch to $dir2
do {
//if true this if not this
$file = $switch ? $dir1->read() : $dir2->read(); //dynamically assigning $dir1 or $dir2 to $file according to value of $switch
$crdir = $switch ? $directory : $devdirectory;
if ($file !== false) {
//
//Your loop handling
//
if($file == '..') continue; // this is the parent folder
if($file == '.') continue; // this is the current folder // this is the php file
if(strpos($file, '.jpg') !== false) continue;
if(strpos($file, '.jpeg') !== false) continue;
if(strpos($file, '.xml') !== false) continue;
if(strpos($file, '.gif') !== false) continue;
if(strpos($file, '.png') !== false) continue;
if(strpos($file, '.png') !== false) continue;
if(strpos($file, '.html') == false) continue; // this is the html file
if($file == '.htaccess') continue; // this is the security file
if($file == 'filestat.txt') continue; // this is the stats file
$file = $crdir . '/' . $file;
if(is_dir($file)) continue; // this is the folder
if(!file_exists($file)) continue;
$fileinfo = new SplFileInfo($file); // get file info object
// put the file info into an array with UNIXTIME key.
$files[$fileinfo->getMTime()] = array('name'=>$file,'mtime'=>date('Y:m:d:H:i:s', $fileinfo->getMTime()),'unixtime'=>$fileinfo->getMTime());
$key = md5($file);
if(array_key_exists($key, $stats_array)) {
if($stats_array[$key][0] != date('Y:m:d:H:i:s', $fileinfo->getMTime())) {
$stats_array[$key][2]++;
$stats_array[$key][0] = date('Y:m:d:H:i:s', $fileinfo->getMTime());
}
} else {
$stats_array[$key] = array(
date('Y:m:d:H:i:s', $fileinfo->getMTime()),
$file,
1
);
}
$datetime = new \DateTime();
$datetime->setTimestamp($fileinfo->getMTime());
$files[$fileinfo->getMTime()]['age'] = $datetime->diff(new \DateTime())->format('%H:%I:%S');
if($datetime->diff(new \DateTime())->format('%a') != '0')
{
$days = ($datetime->diff(new \DateTime())->format('%a') == '1') ? ' day ' : ' days ';
$files[$fileinfo->getMTime()]['age'] = $datetime->diff(new \DateTime())->format('%a') . $days . $files[$fileinfo->getMTime()]['age'];
}
//
//END Your loop handling
//
}
elseif ($switch === true) { //switch to $dir2 if not already
$switch = false;
}
else { //if already switched to $dir2, exit loop
break;
}
} while (true);
$dir1->close(); // close the handler
$dir2->close();
ksort($files); // sort array by keys in ascending order
$newest_file = array_pop($files); //extract latest file from array
foreach($stats_array as $stat) {
$counter += $stat[2];
}
printf(
"Counter %s. (%s) Time Since the Last upload: <span class='update_time' mtime='%s'>%s</span>.",
$counter,
$newest_file['mtime'],
$newest_file['unixtime'],
$newest_file['age']// this is formatted date and time string
);
$put = '';
foreach($stats_array as $line) {
$put .= implode("\t",$line)."\n";
}
file_put_contents($filestat_path,$put);
?>
Notice the CONFIG section I added at the top, here you can set and change the paths, they are used everywhere in the script, so you only have to change one value.
Explanation
I basically made a loop that is going through the main directory first and afterwards through the development directory (switching of the $file variable's value is done with the $switch variable, which affets what value is being asigned), all specified by the path variables in the highlighted config area.
Then follows the basically unchanged handling code provided by you, which already does the thing, since all values are stored into one variable an the sorting at the end simultaneosly does the "show only the most recent change of both directorys" thing.
Important to notice is one change though, that has to be made to this code:
The line
$file = $directory . '/' . $file;
has to be changed to
$file = $crdir . '/' . $file;
with adding the following line above the if ($file !== false), too:
$crdir = $switch ? $directory : $devdirectory;
to work with our "value-swapping" of the both directories.
I post array to php try to remove the file in directory but not in array.
Below code foreach can get the file name in array, while get all the files in directory.
I tried the function like below wrong one, put the while in foreach expect find the file not match $row then unlink. But it failed it will remove some files in array.. seems my logic was wrong. did I doing something wrong?
$dir = "img/";
foreach($img_arr as $row) {
print $row; // get : 2.png 3.png 0.png ....
}
$opendir = opendir($dir);
while ($file = readdir($opendir)) {
// if($file != $row && $file!="." && $file!=".."){
print $file; //get : ...2.png 3.png ...0.png ....
// }
}
wrong
$dir = "img/";
foreach($img_arr as $row) {
print $row; // get : 2.png 3.png 0.png ....
$opendir = opendir($dir);
while ($file = readdir($opendir)) {
if($file != $row && $file!="." && $file!=".."){
print $file; // expect get the file not match $row
}
}
}
Use in_array to check if file exists in your $img_arr:
$img_arr = array(.....); // here comes your array
$opendir = opendir($dir);
// don't forget to stop while-loop also
while (($file = readdir($opendir)) !== false) {
if($file!="." && $file!=".." && !in_array($file, $img_arr)){
print $file;
}
}
i wonder how i can transform exactly the following piece of code to scandir instead of readdir?
$path = 'files';
//shuffle files
$count = 0;
if ($handle = opendir($path)) {
$retval = array();
while (false !== ($file = readdir($handle))) {
$ext = pathinfo($file, PATHINFO_EXTENSION);
if ($file != '.' && $file != '..' && $file != '.DS_Store' &&
$file != 'Thumbs.db') {
$retval[$count] = $file;
$count = $count + 1;
} else {
//no proper file
}
}
closedir($handle);
}
shuffle($retval);
scandir returns, quoting :
Returns an array of filenames on
success, or FALSE on failure.
Which means you'll get the full list of files in a directory -- and can then filter those, using either a custom-made loop with foreach, or some filtering function like array_filter.
Not tested, but I suppose something like this should to the trick :
$path = 'files';
if (($retval = scandir($path)) !== false) {
$retval = array_filter($retval, 'filter_files');
shuffle($retval);
}
function filter_files($file) {
return ($file != '.' && $file != '..' && $file != '.DS_Store' && $file != 'Thumbs.db');
}
Basically, here :
First, you get the list of files, using scandir
Then, you filter out the ones you dn't want, using array_filter and a custom filtering function
Note : this custom filtering function could have been written using an anonymous function, with PHP >= 5.3
And, finally, you shuffle the resulting array.
Not sure why you want to do that, here's a much more concise solution though:
$path = 'files';
$files = array();
foreach (new DirectoryIterator($path) as $fileInfo) {
if($fileInfo->isDot() || $fileInfo->getFilename() == 'Thumbs.db') continue;
$files[] = $fileInfo->getFilename();
}
shuffle($files);
To get started with such problems always consult the PHP manual and read the comments, it's always very helpful. It states that scandir returns an array, so you can walk through it with foreach.
In order to be able to delete some entries of the array, here's an example with for:
$exclude = array( ".", "..", ".DS_Store", "Thumbs.db" );
if( ($dir = scandir($path)) !== false ) {
for( $i=0; $i<count($dir); $i++ ) {
if( in_array($dir[$i], $exclude) )
unset( $dir[$i] );
}
}
$retval = array_values( $dir );
Also have a look at the SPL iterators PHP provides, especially RecursiveDirectoryIterator and DirectoryIterator.
Here's a little function to scan a directory without getting the annoying files.
function cleanscandir ($dir) {
$list = [];
$junk = array('.', '..', 'Thumbs.db', '.DS_Store');
if (($rawList = scandir($dir)) !== false) {
foreach (array_diff($rawList, $junk) as $value) {
$list[] = $value;
}
return $list;
}
return false;
}
Outputs an array or false just like scandir does
i have a propably rather simple question:
I'm using the following script to read a folder?
$count = 0;
if ($handle = opendir(PATH)) {
$retval = array();
while (false !== ($file = readdir($handle))) {
$ext = pathinfo($file, PATHINFO_EXTENSION);
if ($file != '.' && $file != '..' && $file != '.DS_Store' && $file != 'Thumbs.db') {
$retval[$count] = $file;
$count = $count + 1;
} else {
//no proper file
}
}
closedir($handle);
}
if a file is an image I print it as an image: print "";
However i wonder how i can display FOLDERS? If i have a subfolder inside of the folder i'm currently running through? how can i print that one?
use glob instead of scandir
$dirs = glob(PATH."/*", GLOB_ONLYDIR);
$images = glob(PATH."/*.[jJ][pJ][gG]");
foreach ($dirs as $name) echo "<b>$name</b><br>\n";
foreach ($images as $name) echo $name."<br>\n";
Use scandir instead of readdir. http://us.php.net/manual/en/function.scandir.php
The code below is part of a function for grabbing 5 image files from a given directory.
At the moment readdir returns the images 'in the order in which they are stored by the filesystem' as per the spec.
My question is, how can I modify it to get the latest 5 images? Either based on the last_modified date or the filename (which look like 0000009-16-5-2009.png, 0000012-17-5-2009.png, etc.).
if ( $handle = opendir($absolute_dir) )
{
$i = 0;
$image_array = array();
while ( count($image_array) < 5 && ( ($file = readdir($handle)) !== false) )
{
if ( $file != "." && $file != ".." && $file != ".svn" && $file != 'img' )
{
$image_array[$i]['url'] = $relative_dir . $file;
$image_array[$i]['last_modified'] = date ("F d Y H:i:s", filemtime($absolute_dir . '/' . $file));
}
$i++;
}
closedir($handle);
}
If you want to do this entirely in PHP, you must find all the files and their last modification times:
$images = array();
foreach (scandir($folder) as $node) {
$nodePath = $folder . DIRECTORY_SEPARATOR . $node;
if (is_dir($nodePath)) continue;
$images[$nodePath] = filemtime($nodePath);
}
arsort($images);
$newest = array_slice($images, 0, 5);
If you are really only interested in pictures you could use glob() instead of soulmerge's scandir:
$images = array();
foreach (glob("*.{png,jpg,jpeg}", GLOB_BRACE) as $filename) {
$images[$filename] = filemtime($filename);
}
arsort($images);
$newest = array_slice($images, 0, 5);
Or you can create function for the latest 5 files in specified folder.
private function getlatestfivefiles() {
$files = array();
foreach (glob("application/reports/*.*", GLOB_BRACE) as $filename) {
$files[$filename] = filemtime($filename);
}
arsort($files);
$newest = array_slice($files, 0, 5);
return $newest;
}
btw im using CI framework. cheers!