rendered paste body<?php
require 'Console/ProgressBar.php';
ob_implicit_flush(true);
class DupeFinder {
private $path;
private $pattern;
public function __construct($path, $pattern = null) {
$this->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();
?>