############################################################################### # Kain Shin's Second Perl Program ############################################################################### #The purpose of this program is to identify all non-mp3 copies of an mp3 file #and move them into another folder to be manually deleted by human hands use strict; use warnings; use File::Find; use File::Copy; use File::Basename; ############################################################################### #User tunables... my $StartingDirectory = "."; my $DestinationDirectory = "./0.DuplicateFilesToBeDeleted"; ############################################################################### #used in main program to detect of the files are conversions of each other... sub IsConversion { #Parameters... my $FilePathA = $_[0]; my $FilePathB = $_[1]; #...Parameters #Make sure at least one of these files is an mp3 file my @SuffixList = ( ".mp3" ); my($FileNameA, $DirectoryA, $SuffixA) = fileparse( $FilePathA, @SuffixList ); my($FileNameB, $DirectoryB, $SuffixB) = fileparse( $FilePathB, @SuffixList ); my $AtLeastOneMp3 = (length($SuffixA) > 0) || (length($SuffixB) > 0); #Chop off the extension (last 4 chars)... #and see if the names match when the extensions are chopped off $FileNameA = substr( $FilePathA, 0, length( $FilePathA )-4 ); $FileNameB = substr( $FilePathB, 0, length( $FilePathB )-4 ); my $NamesMatch = ( $FileNameA eq $FileNameB ); return $AtLeastOneMp3 && $NamesMatch; } ############################################################################### #used in main program to exile the file with the non-mp3 extension into the DestinationDirectory... sub MoveNonMP3File { #Parameters... my $FilePathA = $_[0]; my $FilePathB = $_[1]; #...Parameters my @SuffixList = ( ".mp3", ".m4a", ".wma" ); my($FilenameA, $DirectoryA, $SuffixA) = fileparse( $FilePathA, @SuffixList ); my($FilenameB, $DirectoryB, $SuffixB) = fileparse( $FilePathB, @SuffixList ); my $FileToKeep = $FilePathA; my $FileToMove = $FilePathB; if ( lc($SuffixB) eq ".mp3" ) #Make sure to keep the mp3 { $FileToKeep = $FilePathB; $FileToMove = $FilePathA; } print "=== POTENTIAL DUPLICATE ===\n"; print "KEPT:$FileToKeep\n"; print "MOVE:$FileToMove\n"; my $DestinationName = substr( $FileToMove, 1 ); $DestinationName = "$DestinationDirectory$DestinationName"; mkdir $DestinationDirectory; my $MoveSuccess = move( $FileToMove, $DestinationDirectory ); if ( $MoveSuccess ) { print "TO:$DestinationName\n"; } else { print "FAILED:$DestinationName\n"; print "$!\n"; } } ############################################################################### #called from File::find... my @gFilePaths; my $gLastPath = 0; sub AddFileToPath { my $CurrentFileSize = -s $_; my $CurrentPath = $File::Find::dir; #Not a folder AND not the DestinationDirectory if ( ( $CurrentFileSize > 0 ) && ( $DestinationDirectory ne $CurrentPath ) ) { #Give feedback on which path is being added if ( !$gLastPath || ( $gLastPath ne $CurrentPath ) ) { print "Adding for Analysis:$CurrentPath\n"; $gLastPath = $CurrentPath; } push( @gFilePaths, $File::Find::name ); } } ############################################################################### #Main Program #Fill gFilePaths with sorted path goodness... find( \&AddFileToPath, $StartingDirectory ); @gFilePaths = sort @gFilePaths; print "========================================================================\n"; print "Checking for duplicates...\n"; #Now, check for duplicates... my $gLastFileName = 0; my $bDuplicatesFound = 0; foreach ( @gFilePaths ) { my $CurrentFileName = $_; if ( $gLastFileName && IsConversion( $gLastFileName, $CurrentFileName ) ) { $bDuplicatesFound = 1; MoveNonMP3File( $gLastFileName, $CurrentFileName ); } $gLastFileName = $CurrentFileName; } print "========================================================================\n"; if ( $bDuplicatesFound ) { print "One layer of duplicates have been moved to '$DestinationDirectory'\n"; print "You may need to run this again because only adjacent files are tested against each other\n"; print "Don't forget to delete your '$DestinationDirectory' folder to finalize the pruning of duplicates\n"; } else { print "Congratulations! No duplicates were found\n"; print "Make sure you do not have a rogue '$DestinationDirectory' folder lingering around\n"; }