62

Just curious

        $files = glob(cacheme_directory()."*");
        foreach($files as $file)
        {
            $filemtime=filemtime ($file);
            if (time()-$filemtime>= 172800)
            {
                unlink($file);
            }
        }

I just want to make sure if the code is correct or not. Thanks.

buschtoens
  • 7,435
  • 9
  • 37
  • 57
user4951
  • 31,039
  • 51
  • 162
  • 275
  • 3
    please use the search function before asking http://stackoverflow.com/search?q=delete+files+older+php – Gordon Jan 23 '12 at 00:00
  • 2
    possible duplicate of [How to delete files from directory based on creation date in php](http://stackoverflow.com/questions/2205738/how-to-delete-files-from-directory-based-on-creation-date-in-php) – Gordon Jan 23 '12 at 00:02
  • It's not duplicate. The one I wrote is simple and I only want to ask if this is correct or not which is a much easier question. – user4951 Jan 23 '12 at 01:49
  • @JimThio asking whether it works is not a real question. Write a UnitTest or simply try it in a test folder. And yes, this is a duplicate of the linked one. It covers exactly the same grounds. And there is more duplicates in the linked search. – Gordon Jan 23 '12 at 08:28
  • Well I got nice suggestions on how to improve it at least. – user4951 Jan 24 '12 at 01:15

11 Answers11

127

You should add an is_file() check, because PHP normally lists . and .., as well as sub-directories that could reside in the the directory you're checking.

Also, as this answer suggests, you should replace the pre-calculated seconds with a more expressive notation.

<?php
  $files = glob(cacheme_directory()."*");
  $now   = time();

  foreach ($files as $file) {
    if (is_file($file)) {
      if ($now - filemtime($file) >= 60 * 60 * 24 * 2) { // 2 days
        unlink($file);
      }
    }
  }
?>

Alternatively you could also use the DirectoryIterator, as shown in this answer. In this simple case it doesn't really offer any advantages, but it would be OOP way.

Community
  • 1
  • 1
buschtoens
  • 7,435
  • 9
  • 37
  • 57
74

The easiest way is by using DirectoryIterator:

<?php
if (file_exists($folderName)) {
    foreach (new DirectoryIterator($folderName) as $fileInfo) {
        if ($fileInfo->isDot()) {
        continue;
        }
        if ($fileInfo->isFile() && time() - $fileInfo->getCTime() >= 2*24*60*60) {
            unlink($fileInfo->getRealPath());
        }
    }
}
?>
Mojtaba
  • 4,536
  • 4
  • 19
  • 38
  • 7
    This works for me, but is slighlty faster if you just calculate time() and 2*24*60*60 once before the while loop and use variables in the loop. – Lisa DeBruine Apr 06 '15 at 11:51
  • I'd just like to say thanks. This honestly should be the chosen answer. – Bravo Delta May 03 '16 at 23:54
  • works great and learned about the DirectoryIterator which is awesome! – William Howley Nov 27 '16 at 23:22
  • 1
    Is the `isDot()` check necessary? Won't the `isFile()` check suffice for that? – ashnazg Jun 28 '18 at 15:38
  • 1
    Note: If your'e using WIndows `getCTime()` is the file creation time, so you might want to use `getMTime()` if you want to use last modified time instead of creation time. – IMB Jul 21 '18 at 11:43
20

Another simplier and more modern way, using FilesystemIterator.

I'm using 'logs' directory as an example.

$fileSystemIterator = new FilesystemIterator('logs');
$now = time();
foreach ($fileSystemIterator as $file) {
    if ($now - $file->getCTime() >= 60 * 60 * 24 * 2) // 2 days 
        unlink('logs/'.$file->getFilename());
}

Main advantage is: DirectoryIterator returns virtual directories "." and ".." in a loop. But FilesystemIterator ignores them.

Community
  • 1
  • 1
Maksim.T
  • 511
  • 4
  • 17
12

I reckon this is much tidier and easier to read and modify.

$expire = strtotime('-7 DAYS');

$files = glob($path . '/*');

foreach ($files as $file) {

    // Skip anything that is not a file
    if (!is_file($file)) {
        continue;
    }

    // Skip any files that have not expired
    if (filemtime($file) > $expire) {
        continue;
    }

    unlink($file);
}
Leon
  • 121
  • 1
  • 3
5
/* Delete Cache Files Here */
$dir = "cache/"; /** define the directory **/

/*** cycle through all files in the directory ***/
foreach (glob($dir."*") as $file) {
//foreach (glob($dir.'*.*') as $file){

/*** if file is 24 hours (86400 seconds) old then delete it ***/
if (filemtime($file) < time() - 172800) { // 2 days
    unlink($file);
    }
}

Hope it help you.

Martin
  • 20,858
  • 7
  • 60
  • 113
Lachit
  • 61
  • 1
  • 4
4

Looks correct to me. I'd just suggest you replace 172800 with 2*24*60*60 for clarity.

Niet the Dark Absol
  • 311,322
  • 76
  • 447
  • 566
3

Here is an example of how to do it recursively.

function remove_files_from_dir_older_than_x_seconds($dir,$seconds = 3600) {
    $files = glob(rtrim($dir, '/')."/*");
    $now   = time();
    foreach ($files as $file) {
        if (is_file($file)) {
            if ($now - filemtime($file) >= $seconds) {
                echo "removed $file<br>".PHP_EOL;
                unlink($file);
            }
        } else {
            remove_files_from_dir_older_than_x_seconds($file,$seconds);
        }
    }
}

remove_files_from_dir_older_than_x_seconds(dirname(__file__).'/cache/', (60 * 60 * 24 * 1) ); // 1 day
2

Be aware that you'll run into problems if you have a very large number of files in the directory.

If you think this is likely to affect you, consider using a lower level approach such as opendir.

John Carter
  • 52,342
  • 26
  • 107
  • 142
1

@maksim-t answer can be improved a bit:

  1. Calculate the oldest "allowed" from the start, instead of calculating it on every iteration.
  2. Use Modification time, instead of creation time, because otherwise you may remove files, that were updated recently.
  3. Use getPathname instead of getFilename, so that there will be not need for concatenation of the path.
#Initiate iterator
$fileSI = new FilesystemIterator($this->files);
#Get the oldest allowed time
$oldest = time() - ($maxFileAge * 86400);
#Iterate the files
foreach ($fileSI as $file) {
    #Check time
    if ($file->getMTime() <= $oldest) {
        #Remove the file
        @unlink($file->getPathname());
    }
} 
Simbiat
  • 145
  • 1
  • 10
0
/** It deletes old files.
 *  @param string $dir Directory
 *  @param int $secs Files older than $secs seconds
 *  @param string $pattern Files matching $pattern
 */
function delete_oldfiles($dir,$secs,$pattern = "/*")
{
    $now = time();
    foreach(glob("$dir$pattern") as $f) {
      if (is_file($f) && ($now - filemtime($f) > $secs)) unlink($f);
    }
}
Miguel
  • 1
0
(time()-filectime($path.$file)) < 172800 //2 days

If the current time and file are changed time are within 172800 seconds of each other, then.

 if (preg_match('/\.pdf$/i', $file)) {
     unlink($path.$file);
 }

Well, if its there still any confusion you just need to change the operator from the first line of code.