Search code examples
phpdatabase-backupsunlink

How to delete files older than 7 days, with specific filename or file extension


I have a index.php script that runs every night to backup a mySQL database (through CRON) on my website. The script store the file in the folder where the script is. I wanted to created another script that would delete backup files older than 7 days. So I used this one from tdebatty on GitHub:

<?php

function delete_older_than($dir, $max_age) {
  $list = array();
  
  $limit = time() - $max_age;
  
  $dir = realpath($dir);
  
  if (!is_dir($dir)) {
    return;
  }
  
  $dh = opendir($dir);
  if ($dh === false) {
    return;
  }
  
  while (($file = readdir($dh)) !== false) {
    $file = $dir . '/' . $file;
    if (!is_file($file)) {
      continue;
    }
    
    if (filemtime($file) < $limit) {
      $list[] = $file;
      unlink($file);
    }
    
  }
  closedir($dh);
  return $list;

}


// An example of how to use:
$dir = "/my/backups";
$to = "[email protected]";

// Delete backups older than 7 days
$deleted = delete_older_than($dir, 3600*24*7);

$txt = "Deleted " . count($deleted) . " old backup(s):\n" .
    implode("\n", $deleted);

mail($to, "Backups cleanup", $txt);

The script works well, but I would like to limit deletion to files starting with "XXX' or .sql.gz files. In the backup folder i have all the .sql.gz backup alongside the index.php script that is used daily to backup. This index.php file is not modified as the days go by, so it gets older and it is deleted by the deletion script at some point.

Thank you !

I tried to modify existing if conditions: if (!is_file($file) || strpos($file, "XXX") !== 0) { or if (filemtime($file) < $limit && strpos($file, "XXX") === false) { or if (pathinfo($file, PATHINFO_EXTENSION) == 'sql.gz' && filemtime($file) < $limit) {

I also tried to add another if condition in the loop:

if (strpos($file, "XXX") !== 0) {
        continue;
    }

None of these works and I don't understand why. Script doesn't work anymore, nothin happens. Any clue? Sorry if it's obvious, I'm still learning :)


Solution

  • Here your mistake, the script redefine $file with this $file = $dir . '/' . $file; and you create a condition strpos($file, "XXX") !== 0, so your condition will like this strpos("/YOURPATH/XXX", "XXX") !== 0

    Also you create this condition pathinfo($file, PATHINFO_EXTENSION) == 'sql.gz' is wrong because output of pathinfo($file, PATHINFO_EXTENSION) is only extension (gz,txt,etc)

    Here the working code

    function delete_older_than($dir, $max_age, $prefix = null, $extension = null) {
      $list = array();
      
      $limit = time() - $max_age;
      
      $dir = realpath($dir);
      
      if (!is_dir($dir)) {
        return;
      }
      
      $dh = opendir($dir);
      if ($dh === false) {
        return;
      }
      
      while (($file = readdir($dh)) !== false) {
        $fullpath = $dir . '/' . $file;
        if (!is_file($fullpath)) {
          continue;
        }
        
        if ($prefix !== null && !(strpos($file, $prefix) === 0)) {
          continue;
        }
        
        if ($extension !== null && !(strlen($file) - strlen($extension) == strrpos($file,$extension))) {
          continue;
        }
        
        if (filemtime($fullpath) < $limit) {
          $list[] = $fullpath;
          unlink($fullpath);
          echo "Deleted $fullpath \n";
        }
        
      }
      closedir($dh);
      return $list;
    }
    

    For testing, use this code for generate a random file.

    // Function for generate random file for testing only
    function randomFile($extension) {
        $characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        $randomString = '';
        for ($i = 0; $i < 10; $i++) {
            $randomString .= $characters[rand(0, strlen($characters) - 1)];
        }
        $filename = $randomString . $extension;
        return $filename;
    }
    function generateFile($extension, $prefix = '') {
        
    
        $directory = '/tmp'; // The directory path where the files will be created
        //$extension = ".sql.gz"; // The desired file extension
    
        for ($i = 1; $i <= 10; $i++) {
            $filename = $directory . '/' . $prefix . randomFile($extension); // Construct the file name
            $content = 'This is file number ' . $i; // Content to be written in the file
    
            // Create the file and write the content
            file_put_contents($filename, $content);
    
            echo "File created: $filename \n";
        }
    }
    

    Then use it

    generateFile(".sql.gz","XXX");
    generateFile(".sql.gz","IAMUNDELETED");
    generateFile(".txt");
    sleep(1);
    delete_older_than("/tmp", 0, "XXX","");
    print_r(scandir("/tmp"));
    delete_older_than("/tmp", 0, "",".txt");
    print_r(scandir("/tmp"));
    

    Here live code test : https://onlinephp.io/c/3fc02