path = realpath($path); $this->pattern = $pattern; } public function find() { echo "Finding files...\n"; $filelist = $this->_findFiles($this->path, $this->pattern); $same_filesizes = $this->_checkFilesizes($filelist); // Check the first 16 bytes of the file echo "Checking contents...\n"; $bar = new Console_ProgressBar('%current%/%max% [%bar%] %percent%', '=>', ' ', 80, sizeof($same_filesizes)); $same_contents = Array(); for($i = 0; $i < sizeof($same_filesizes); $i++) { $out = $this->_checkContents($same_filesizes[$i]); if(sizeof($out) > 0) { $same_contents[] = $out[0]; } $bar->update($i + 1); } echo "\n"; // Find the ones with matching checksums $bar = new Console_ProgressBar('%current%/%max% [%bar%] %percent%', '=>', ' ', 80, sizeof($same_contents)); $same_checksums = Array(); for($i = 0; $i < sizeof($same_contents); $i++) { $out = $this->_checkChecksums($same_contents[$i]); if(sizeof($out) > 0) { $same_checksums[] = $out[0]; } $bar->update($i + 1); } echo "\n"; return $same_checksums; } private function _findFiles($path, $pattern = null) { $filelist = Array(); $handle = dir($path); while( ($file = $handle->read()) !== false) { $name = $path . '/' . $file; if(!is_readable($name)) continue; // Don't even bother trying if($file[0] == '.') continue; if(is_link($name)) continue; if(is_dir($name)) { $filelist = array_merge($filelist, $this->_findFiles($name, $pattern)); } else if(is_file($name)) { if($pattern != null) { if(preg_match($pattern, $file)) { $filelist[] = $name; } } else { $filelist[] = $name; } } } return $filelist; } // Make arrays of files with the same size private function _checkFilesizes($filelist) { $filesizes = Array(); foreach($filelist as $file) { $size = filesize($file); if($size < 1) continue; // wtf? if(!isset($filesizes[$size])) $filesizes[$size] = Array(); $filesizes[$size][] = $file; } $output = Array(); foreach($filesizes as $size => $files) { if(sizeof($files) > 1) $output[] = $files; } return $output; } private function _checkContents($filelist) { $signatures = Array(); foreach($filelist as $file) { $fp = fopen($file, "r"); if(!$fp) throw new Exception("Couldn't open file: $file"); $signature = fread($fp, 16); fclose($fp); if(!isset($signatures[$signature])) $signatures[$signature] = Array(); $signatures[$signature][] = $file; } $output = Array(); foreach($signatures as $signature => $files) { if(sizeof($files) > 1) { $output[] = $files; } } return $output; } private function _checkChecksums($filelist) { $sums = Array(); foreach($filelist as $file) { $sum = md5_file($file); if(!isset($sums[$sum])) $sums[$sum] = Array(); $sums[$sum][] = $file; } $output = Array(); foreach($sums as $sum => $files) { if(sizeof($files) > 1) { $output[] = $files; } } return $output; } } $finder = new DupeFinder("."); $dupes = $finder->find(); ?>