# Finding Duplicate MP3s

**URL:** <https://www.ruby-forum.com/t/finding-duplicate-mp3s/121807>\
**Category:** Ruby\
**Created:** [December 1, 2007, 4:16am UTC](https://www.ruby-forum.com/t/finding-duplicate-mp3s/121807 "2007-12-01T04:16:56Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![garg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/dec6dc/32.png) [@garg](https://www.ruby-forum.com/u/garg)\
**Post date:** [December 1, 2007, 4:16am UTC](https://www.ruby-forum.com/t/finding-duplicate-mp3s/121807/1 "2007-12-01T04:16:56Z")

</div>

I’m a RubyNoobie and I am writing a few random scripts to learn the  
language. Would it be alright to post scripts to get them criticized by  
pros?

This is supposed to search a folder to find duplicate MP3s and move them  
to a destination directory.

\*When you search a directory structure with lots of branches then  
mp3info gives an error.  
\*The source and destination folders NEED to have the backslash \ or else  
the script does horrible things. So it needs better input checking

I don’t always know the best programmer practices and it would help me  
if someone can make suggestions.

# Finds duplicate MP3s and move them to stated destination

# usage: duplicatemp3.rb c:\source\dir\ c:\destination\dir\

# the ending \ slash is REQUIRED

require “mp3info”  
require “ftools”

class DuplicateMP3  
def initialize()  
unless ARGV.length == 2  
puts “usage: duplicatemp3.rb c:\source\dir\ c:\destination\dir”  
exit  
end  
@dir\_source = ARGV[0]  
@dir\_destination = ARGV[1]

```
showallduplicates()

```

end

def showallduplicates()  
directory = @dir\_source  
duplicates = Hash.new { |h,k| h[k] = [] }  
Dir.chdir(@dir\_source)

#Check if the file is a file then  
#Make a unique ID with the mp3 title and mp3 song length combined  
#Enter unique into the hash as a key  
#If unique key is already in the hash then move the file to destination  
folder

```
Dir["**/*.mp3"].each do |file|
  if File.file?(file)
    Mp3Info.open(file) do |mp3|
      unique = mp3.tag.title.to_s + mp3.length.to_s
      if (duplicates.has_key?(unique))
        puts "duplicate: #{file}. Moving..."
        movedupes(file)
      else
          duplicates[unique].push(file)
      end
    end
  end
end

```

end

def movedupes(file)  
source = @dir\_source + file.to\_s  
dest = @dir\_destination + File.basename(file.to\_s)  
File.move(source, dest)  
puts “file moved”  
end

end

find = DuplicateMP3.new()

---

<div class="post-metadata">

**Author:** ![garg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/dec6dc/32.png) [@garg](https://www.ruby-forum.com/u/garg)\
**Post date:** [December 4, 2007, 1:56am UTC](https://www.ruby-forum.com/t/finding-duplicate-mp3s/121807/2 "2007-12-04T01:56:06Z")

</div>

On Nov 30, 2007 7:16 PM, Khurrum Ma [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> I don’t always know the best programmer practices and it would help me

Sure.

> class DuplicateMP3  
> def initialize()  
> unless ARGV.length == 2  
> puts "usage: duplicatemp3.rb c:\source\dir\ c:\destination\dir"  
> exit  
> end  
> @dir\_source = ARGV[0]  
> @dir\_destination = ARGV[1]
> 
> showallduplicates()

Meh. I’d pass source and dest to initialize directly. I’d call  
showallduplicates() on the DuplicateMP3 object directly. If you really  
want, add a class method like

def self.do\_it(src, dest)  
mover = new(src,dest)  
mover.showallduplicates()  
end

Maybe. I’m shaky on this actually needing to be a class, but I guess it  
works okay…

end

> folder

Here’s the biggest thing: look into using Find (in the standard  
library.)  
It’s almost always superior to Dir, unless you really don’t want to  
recurse  
at all.

> Dir[“\*\*/\*.mp3”].each do |file|  
> if File.file?(file)  
> Mp3Info.open(file) do |mp3|  
> unique = mp3.tag.title.to\_s + mp3.length.to\_s

I’d use [mp3.tag.title.to\_s, mp3.length] instead. It’s certainly a  
corner  
case, but it’d be a shame if you had “song” that was 210 long treated as  
a  
dupe of “song2”, 10 long.

> ```
> if (duplicates.has_key?(unique))
> puts "duplicate: #{file}. Moving..."
> movedupes(file)
> else
> duplicates[unique].push(file)
> 
> ```

Meh again. Use a regular hash, and replace this line with  
“duplicates[unique] = true” since you don’t ever use the values of the  
duplicates hash.

```
     end

```

> ```
> end
> end
> 
> ```
> 
> end  
> end
> 
> def movedupes(file)

And the solution to your input problem is:  
“source = File::join(@dir\_source, file.to\_s)”  
If you use Find, it’ll be a little easier here, and tricker in the  
destination, because Find will give you the full path anyway.

> source = @dir\_source + file.to\_s

Instead of File.basename, you’ll want to use something else. If you’re  
using Find, you’ll get reasonably full paths, so you might be able to do  
something like  
file.to\_s.sub(%r{^#{Regexp::escape(@dir\_source)}}, “”)  
which will find the source path and replace it with an empty string. I  
don’t know a better way work with the paths, honestly.  
And you’d use File::join again here, as well.

> dest = @dir\_destination + File.basename(file.to\_s)  
> File.move(source, dest)  
> puts “file moved”  
> end
> 
> end
> 
> find = DuplicateMP3.new()

Ultimately, I think you want to have this look like  
if($0 == **FILE** )  
#Put the ARGV.length check here  
find = DuplicateMP3.new(ARGV[0], ARGV[1])  
find.showallduplicates()  
end

---

<div class="post-metadata">

**Author:** ![garg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/dec6dc/32.png) [@garg](https://www.ruby-forum.com/u/garg)\
**Post date:** [December 5, 2007, 10:52pm UTC](https://www.ruby-forum.com/t/finding-duplicate-mp3s/121807/3 "2007-12-05T22:52:29Z")

</div>

Judson L. wrote:

> On Dec 3, 2007 4:55 PM, Judson L. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

Thank you very much. This is incredibly helpful. I’m sure this will be  
useful to other beginners as well.

---

<div class="post-metadata">

**Author:** ![garg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/dec6dc/32.png) [@garg](https://www.ruby-forum.com/u/garg)\
**Post date:** [December 4, 2007, 2:03am UTC](https://www.ruby-forum.com/t/finding-duplicate-mp3s/121807/4 "2007-12-04T02:03:43Z")

</div>

On Dec 3, 2007 4:55 PM, Judson L. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
