PHP: Recursive Cleanup (for Web Servers)

Posted on October 4, 2011 by Jimmy K. in Articles, Tutorials.

For as long as I can remember, I’ve loathed .DS_Store and Thumbs.db files. They always seem to crawl their way onto my hosting servers.

By definition, the .DS_Store file is “a hidden file created by Apple’s Mac OS X operating system to store custom attributes of a folder such as the position of icons or the choice of a background image” and the Thumbs.db file is “used to store thumbnail images for Windows Explorer’s thumbnail view. This speeds up the display of images as the smaller images do not need to be recalculated every time the user views the folder.” Neither of these files are particularly useful on a hosting server.

So… how do we fix it?!

I wrote a simple class that performs a recursive loop and finds and deletes all occurrences of the .DS_Store and Thumbs.db files. Then I decided to open it up a bit and added functionality for additional file names (error_log, for example). Specific files can be added or skipped using the jRegisterDeleteFile() and jRegisterIngoreFile() functions.

Onward, to the code!

Listed below is the code for this class.

<?php

	class RecursiveCleanup {
	
		/*
		 *
		 *   Class Name: RecursiveCleanup
		 *   Author: Jimmy K.
		 *   Website: http://www.endseven.net/
		 *   Version: 1.0
		 *
		 *   I wrote this class to delete pesky .DS_Store (Mac) and Thumbs.db (Windows) files. 
		 *   If you  disagree with any of it's contents, don't use it. ;)
		 *
		 */
		
		var $sDocumentRoot = ""; // the directory to start in..
		var $bOutputTree = true; // whether or not to output directory trees..
		var $aFilesToIgnore = array(".", ".."); // the list of files to ignore..
		var $aFilesToDelete = array(".DS_Store", "Thumbs.db"); // the list of files to delete..
		var $iNumDeletedFiles = 0; // the number of deleted files..
		
		/* the constructor for this object. */
		public function __construct($sDocumentRoot, $bOutputTree) {
		
			$this->sDocumentRoot = $sDocumentRoot;
			$this->bOutputTree = $bOutputTree;
					
		}
		
		/* loop through the directory. */
		public function jLoopDirectory($sPath) {
			
			$oHandle = opendir($sPath);
			
			while (false !== ($sFile = readdir($oHandle))) {
				
				$sFullFilename = $sPath . "/" . $sFile;
				
				if (!in_array($sFile, $this->aFilesToIgnore)) {
					
					if (is_dir($sFullFilename)) {
						
						if ($this->bOutputTree) echo "<span style=\"color: #000;\">$sFullFilename/</span><br />";
						$this->jLoopDirectory($sFullFilename);
						
					} else if (in_array($sFile, $this->aFilesToDelete)) {
						
						echo "<span style=\"color: #900;\">$sFullFilename</span> [Deleted]<br />";
						unlink($sFullFilename); $this->iNumDeletedFiles++;
					
					} else {
						
						if ($this->bOutputTree) echo "$sFullFilename<br />";
					
					}
				
				}
			
			}
			
			@closedir($oHandle);
		
		}
		
		/* register a file to ignore. */
		public function jRegisterIgnoreFile($sFilename) {
			
			if (!in_array($sFilename, $this->aFilesToIgnore)) {
				array_push($this->aFilesToIgnore, $sFilename); // add the filename to the array..
			}
		
		}
		
		/* register a file to delete. */
		public function jRegisterDeleteFile($sFilename) {
			
			if (!in_array($sFilename, $this->aFilesToDelete)) {
				array_push($this->aFilesToDelete, $sFilename); // add the filename to the array..
			}
		
		}
		
	}
	
	?>

Listed below is an example that demonstrates how to use this class.

<?php

	require("../RecursiveCleanup.class.php");
	$oRecursiveCleanup = new RecursiveCleanup("/home/jklatt86/public_html", false);
	
	?>
	
	<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
	<html xmlns="http://www.w3.org/1999/xhtml">
	<head><title>END[SEVEN] Web Development &raquo; Recursive Cleanup</title>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
	
	<link href="http://cloud.endseven.net/css/default/1.1/style.css" rel="stylesheet" />
	<link href="http://cloud.endseven.net/css/cloud/1.0/style.css" rel="stylesheet" />
	
	<script type="text/javascript">
	
		var _gaq = _gaq || [];
		_gaq.push(['_setAccount', 'UA-7760848-6']);
		_gaq.push(['_setDomainName', 'endseven.net']);
		_gaq.push(['_trackPageview']);
		
		(function() {
		var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
		ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
		var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
		})();
	
	</script>
	
	</head><body>
	
	<table style="width: 100%; height: 100%;">
	<tr style="width: 100%; height: 100%;">
	<td style="width: 100%; height: 100%;" class="example-container">
	
	<table style="width: 720px; margin: auto;">
	<tr style="width: 720px; height: auto;">
	<td style="width: 720px; height: auto;" class="example-column">
	
		<?php
		
		echo "Registering ignore file: <strong>cgi-bin</strong>...<br />";
		$oRecursiveCleanup->jRegisterIgnoreFile("cgi-bin");
		
		echo "Registering delete file: <strong>error_log</strong>...<br />";
		$oRecursiveCleanup->jRegisterDeleteFile("error_log");
		
		echo "Creating temporary .DS_Store file...<br />";
		
		$oHandle = fopen("./.DS_Store", "w+");
		fwrite($oHandle, "This is a sample .DS_Store file.");
		fclose($oHandle);
		
		$oRecursiveCleanup->jLoopDirectory($oRecursiveCleanup->sDocumentRoot);
		echo "<strong># of Deleted Files: " . $oRecursiveCleanup->iNumDeletedFiles . "</strong>";
		
		?>
		
	</td>
	</tr>
	</table>
	
	</td>
	</tr>
	</table>
	
	</body>
	</html>
	

I hope you find this class helpful. I guarantee that (being the obsessive compulsive person that I am) it will help me sleep at night. You can download the source files here.

This class has also been added to the END[SEVEN] Cloud.

Tags: , , , , ,

 
 
 

If you like this, please leave a comment.