简体   繁体   中英

PHP: checking files from two directories (or recursively over subdirectories)

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM