Saturday, June 30, 2012

Deleting X Oldest Files in a Directory Using PHP


Sometimes, when processing uploaded files for instance, we want to save the files for posterity.  But, over a couple years, the amount of disk space this consumes can get out of hand—particularly for really large files like database backups. 

So I wrote the following PHP function to police the directory for cases like this.  This function will keep some number of files in directory “$path” determined by the “$numToKeep” argument.  It will delete any other older files. 

It gets the file name and age (creation timestamp actually, which is not quite the same as age) in two separate arrays.  It then sorts both arrays using the file timestamp array as a key leaving you a list of file names sorted by age.  But age and timestamp are inversely related.  So we have to sort by DESC timestamp to get a list sorted by ASC age.  

The “unlink” command is permanent as I am sure you are aware.   I try to step up to another level of careful anytime I create and deploy a function of this sort.

I’ve actually used and tested this function.  It seems to works correctly.  However, I of course accept no responsibility or liability if it eats your homework…or all your company’s financial data.  Test, test, and then test again before deploying something like this against a live system.

   /**
    * Delete oldest files in a directory
    * must exist or this function will throw an exception
    *
    * @param string $path
    * @param int $numToKeep
    *
    * @return bool
    */
   private function _deleteOldestFiles($path, $numToKeep) {
  
      $fileList = array();
      $fileDate = array();
      $handle = opendir($path);
      if($handle) {
         while(false !== ($file = readdir($handle))) {
            if($file != "." && $file != "..") {
               $fileList[] = $path . $file;
               $fileDate[] = filemtime($path . $file);
            }
         }
         closedir($handle);
         array_multisort ($fileDate, SORT_DESC, $fileList);
         for ($i=$numToKeep; $i < count($fileList); $i++) {
            unlink($fileList[$i]);
            $this->logger->log('[' . __METHOD__ . '] ' .
                  'Deleted file number ' . $i . ' : ' . $fileList[$i] .
                  ' with creation date ' . $fileDate[$i]);
         }
      } else {
         $this->logger->log('[' . __METHOD__ . '] ' .
             'Error: Failed to find target deletion directory at: ' . $path);
         throw new Exception("Failed to find deletion directory: " . $path);
      }
   }


No comments:

Post a Comment