Directories to look over -p Define RegEx patterns -r Rename file recursively -s Strings that will replace the matches Optional: -e Exclude defined pattern -l Output log file -t Test without modifying anything " ) ; //------- End Usage ----------- class ArgvParser { //parseOptions utilitiese by tgckpg static function PARSE ( $argStream, $handler ) { //Chop first useless argument -- argv[0] array_shift ( $argStream ) ; //Initiate ArrayObject for iterator $arrayobject = new ArrayObject ( $argStream ) ; //Initiate iterator for iteration $iterator = $arrayobject->getIterator(); //If options is set first if( $iterator->valid() && preg_match ( '/^-\w$/', $iterator->current() ) ) { //iterate through whole argument stream for ( ; $iterator->valid(); $iterator->next() ) { //Check if reached next option if( preg_match ( '/^-\w$/', $opts = $iterator->current() ) ) { //Get current options $currOpt = $opts; //echo "$currOpt\n"; //Test if next stream is an option for ( $iterator->next(); $iterator->valid(); $iterator->next() ) { if ( preg_match ( '/^-\w$/', $opts = $iterator->current() ) ) { //echo "$currOpt $opts\n"; $handler($currOpt); $currOpt = $opts; } else break; //var_dump($iterator->valid()); } }//End if //echo "$currOpt $opts\n"; $handler($currOpt, $opts); //A temporary fix for infinite loop if(!$iterator->valid()) break; }// End for //If option is not set first. } else { //Try other approach. }// End if } } class RegRename { //Define globals private $test = false; private $recursive = false; private $searchDirs = array(); private $patterns = array(); private $replaceStrs = array(); private $excludes = array(); private $logfile = NULL; public function begin() { $this->validateOptions(); //------- Begin Operations ------- foreach ( $this->searchDirs as $dir ) { $this->elog("Directory: $dir\nBuilding file list ..."); if ( $this->recursive ) { $fileList = $this->getWholeFileList($dir); } else { $fileList = $this->getFileList($dir); } $this->elog("Searching ..."); foreach ( $fileList as $file ) { // // Get the file name // RegExplained: // Example: /foo/bar/foobar.bar // $matches[0][0] is the whole string "/foo/bar/foobar.bar" // // ^(.+?) // This gets the file path "/foo/bar/" for $matches[1][0] // // ([^\/\\\\]+)$ // This gets the file name "foobar.bar" for $matches[2][0] // preg_match_all('/^(.+?)([^\/\\\\]+)$/', $file, $matches ); $newName = $matches[2][0]; foreach ( $this->patterns as $key => $pattern ) { //Rename over the patterns $newName = preg_replace( $pattern, $this->replaceStrs[$key], $newName ); } if( $matches[2][0] != $newName ) { // Excluede any matches foreach ( $this->excludes as $key => $pattern ) { if(preg_match_all($pattern, $file)) { $this->elog("S File \"{$matches[2][0]}\" excluded on $pattern"); continue 2; } } if( $this->test ) { $this->elog("R File \"{$matches[2][0]}\" will be renamed to \"$newName\""); } else { rename ( $file, "{$matches[1][0]}$newName" ); } if ( $this->logfile ) { file_put_contents($this->logfile, $this->log); } }/* else { echo "File \"{$matches[0][0]}\" will not be renamed\n"; } //*/ } $this->elog(); } if ( $this->test ) $this->elog("*** Test enabled ***\n"); //------- End Operations -------*/ } public function setOption( $item, $value = NULL ) { switch($item) { case "-d": if($value) $this->searchDirs[] = $value; break; case "-p": if($value) $this->patterns[] = $value; break; case "-r": $this->recursive = true; break; case "-s": if($value) $this->replaceStrs[] = $value; break; case "-t": $this->test = true; break; case "-e": $this->excludes[] = $value; break; case "-l": $this->logfile = $value; break; default: //Do nothing } } //------- Main Functions -------- function elog( $line = "" ) { $this->log .= $line; $this->log .= "\n"; echo "$line\n"; } private function getDirName ( $dir ) { return is_dir ( $dir ) ? $dir : dirname ( $dir ) ; } private function getFileList ( $dir ) { $fileList = array(); $iterator = new DirectoryIterator ( $this->getDirName ( $dir ) ) ; foreach ( $iterator as $fileinfo ) { if ( $fileinfo->isFile() ) { $fileList[] = $dir."/".$fileinfo->getFilename(); } } return $fileList; } private function getDirList ( $dir ) { $dirList = array(); $iterator = new DirectoryIterator ( $this->getDirName ( $dir ) ) ; foreach ( $iterator as $fileinfo ) { if ( $fileinfo->isDir() && !$fileinfo->isDot()) { $dirList[] = $fileinfo->getFilename(); } } return $dirList; } private function getWholeDirList ( $dir ) { $wholeDirList = array(); //getWholeDirList will stop untill getDirList return an empty array. foreach ( $this->getDirList ( $dir ) as $file ) { //Store found path $wholeDirList[] = "$dir/$file"; //Method getWholeDirList will self-iterate if sub-directories exist. $wholeDirList = array_merge ( $wholeDirList, $this->getWholeDirList ( "$dir/$file" ) ) ; } return $wholeDirList; } private function getWholeFileList ( $dir ) { //Get the first level list. $wholeFileList = $this->getFileList( $dir ); //getWholeDirList and search its files. foreach ( $this->getWholeDirList ( $dir ) as $dir ) { $wholeFileList = array_merge ( $wholeFileList, $this->getFileList ( $dir ) ) ; } return $wholeFileList; } private function validateOptions ( ) { try { if(count($this->searchDirs) == 0) throw new Exception("Search directory is missing"); else if(count($this->patterns) == 0) throw new Exception("Search pattern is missing"); else if(count($this->replaceStrs) == 0) throw new Exception("Replacement string is missing"); else if(count($this->replaceStrs) != count($this->patterns)) throw new Exception("Replacement string and pattern count not match"); } catch(Exception $e) { var_dump( $GLOBALS ); die("Error: $e.\n"); } } //------- End Main Functions -------- } $rrgr = new RegRename(); ArgvParser::PARSE ( $argv, array($rrgr, 'setOption') ) ; $rrgr->begin(); ?>