Recursively delete files using PHP

Sometimes it is nice to be able to recursively delete specific files in folder structures using PHP. For instance imagine the case when you want to delete an image that exists in multiple versions, such as the original, a thumbnail and an icon version.

These versions are kept inside subfolders names resized, thumbnails and icons respecively. Furthermore, imagine the case that there exist multiple different thumbnail dimension formats, such as 300×150 and 150×75. Finally, let’s say that these dimensions are part of the original filename, such as original_300x150.png and original_150x75.png.

In order to automatically also delete these resized versions the base folder needs to be parsed recursively to delete all matching files contained.

The following function recursively deletes all occurrences of files matching the filename specified by an absolute path ($filepath). Additionally, the second parameter $deleteFilesStartingWithFilename defines whether to do a regular expression match against all files contained in the base folder and any subfolders contained in it.

For instance, a call with $filepath=’/path/file.png’ with $deleteFilesStartingWithFilename=true will delete all files starting with “file”, such as “file_1.png” or “fileX.jpg”.

Caution: At the moment it ignores the extension when using $deleteFilesStartingWithFilename=true, so it will also delete file.JPG when $filepath=’/path/file.PNG’.

public static function recursiveDelete($filepath, $deleteFilesStartingWithFilename=false, $recursion=false, $recursionFilename=null) {
  $sourceFolder = is_dir(realpath($filepath)) ? realpath($filepath) : dirname(realpath($filepath));
        $sourceFilename = basename(realpath($filepath));
        $dir_handle = opendir($sourceFolder);

  if (!$dir_handle)
    return false; //will not recurse unless base file $filepath exists

  while ($file = readdir($dir_handle)) {
    if ($file == '.' || $file == '..')
      continue;

    $filenameToMatch = ($recursion && $recursionFilename ?
                    basename($recursionFilename) : $sourceFilename);

     if (is_file($sourceFolder . '/' . $file)) {
       if ($file === $filenameToMatch ||
            ($deleteFilesStartingWithFilename && preg_match('/^'
             . preg_replace('/' . str_replace('.', '\.', self::getExtension($filenameToMatch, true)) . '$/', '', $filenameToMatch) . '/', preg_replace('/' . str_replace('.', '\.', self::getExtension($file, true)) . '$/', '', $file)))) {
              unlink($sourceFolder . '/' . $file); //delete file
              }
            } else {
                self::recursiveDelete($sourceFolder . '/' . $file, $deleteFilesStartingWithFilename, true, $filenameToMatch);
    }
  }

  closedir($dir_handle);

  return true;
}

TODO: I will update the function to also check for correct (i.e. matching) file extension of the original filename.

As you might have guessed self::getExtension() returns the file extension. The second parameter determines whether to include the ‘.’ of the extension returned.

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *