Jump to content
Sign in to follow this  

iScan - Find and delete duplicate songs in your iTunes library

Recommended Posts


A little app I made because I hate having duplicate songs on my iTunes, and with 2000 songs I'd hate to find them myself. Shockingly, my script found 20 duplicate songs and I saved 82.5MB worth of space.

My script uses a decent comparison method, so some song names that might not be equal might still be picked up. After scanning your library, please uncheck any songs that you do not wish to delete and afterwards click Delete Selected.

iTunes is needed to run the application

#include <GUIConstants.au3>
#include <GUIListView.au3>

Global $listcount = 0, $foundCount, $Found, $iTracks, $Tracks ;some variables that will be used
$GUI = GUICreate("iScan - Delete duplicate songs", 283, 306, 193, 125)
GUICtrlCreateLabel("iScan", 24, 9, 44, 24)
GUICtrlSetFont(-1, 13, 2000, 0, "MS Sans Serif")
$Scan = GUICtrlCreateButton("Scan Library", 88, 8, 89, 25, 0)
$List1 = GUICtrlCreateListView("Song|Artist|Path", 8, 40, 265, 253)
_GUICtrlListView_SetExtendedListViewStyle($List1, $LVS_EX_CHECKBOXES) ;Set listview to checkbox style
_GUICtrlListView_SetColumnWidth($List1, 0, 87) ;even out the widths of the columns
_GUICtrlListView_SetColumnWidth($List1, 1, 87)
_GUICtrlListView_SetColumnWidth($List1, 2, 87)
$Delete = GUICtrlCreateButton("Delete Selected", 184, 8, 89, 25, 0)
GUICtrlSetState(-1,$GUI_DISABLE) ;set it disabled until scan is complete
GUISetState() ;show GUI

While 1
    $msg = GUIGetMsg()
        Case $msg = $Scan ;scan is pressed
            GUICtrlSetState($Scan, $GUI_DISABLE) ;disable scan button until scan is complete
            Scan() ;see Scan()
            GUICtrlSetState($Delete, $GUI_ENABLE) ;enable delete button to allow user to delete checked songs
        Case $msg = $GUI_EVENT_CLOSE
        Case $msg = $Delete
            GUICtrlSetState($Delete, $GUI_DISABLE)
            Delete() ;see Delete()
            GUICtrlSetState($Delete, $GUI_ENABLE)

Func Scan()
    GUICtrlSetData($Scan, "Creating iTunes Object")
    Sleep(100) ;Let it update the GUI before we lag the process by creating the iTunes object (if iTunes is not open)
    $oiTunes = ObjCreate("iTunes.Application")
    If Not IsObj($oiTunes) Then ;Notify user if user does not have iTunes installed on his computer
        MsgBox(0, "", "ERROR: Could not create iTunes object." & @CRLF & @CRLF & "Explanation:" & @CRLF & "iTunes, or some of it's components, are not installed on your computer." & @CRLF & "Now Exiting..")
    $iTracks = $oiTunes.LibraryPlaylist.Tracks ;Get tracks from the library
    Global $total = $iTracks.Count ;$total represents the total songs in the library
    Global $count = 0 ;set values
    Global $Tracks[$total+1][3] ;create an array, the first dimension sized at the number of songs in your library
    ;                           ;the second dimension: [0]=Song  [1]=Artist  [2]=Size
    GUICtrlSetData($Scan, "Scanning..")
    ProgressOn("iScan", "Scanning: ", "0%") ;display progress
    For $i In $iTracks ;for each track found in the library
        $count += 1 ;keep track # of songs
        ProgressSet(Round(($count/$total)*100, 2), Round(($count/$total)*100, 2) & "%", "Scanning: " & $i.Name)
        $Tracks[$count][0] = $i.Name    ;set array member values
        $Tracks[$count][1] = $i.Artist
        $Tracks[$count][2] = $i.Size
    ProgressSet(0, "Comparing: ", "0%") ;now that we have all the values in the array, start comparing each song
    Global $Found[2][2] ;$Found array assures that we don't find 2 of the same duplicate songs
    Global $foundCount = 1
    Global $foundSwitch = False
    Global $SpaceSaved = 0
    For $i = 1 To $total
        ProgressSet(Round(($i/$total)*100, 2), Round(($i/$total)*100, 2) & "%", "Comparing: " & $Tracks[$i][0])
        For $x = 1 To $total
            If PrepareString($Tracks[$i][0]) = PrepareString($Tracks[$x][0]) AND _              ;compare song names (see PrepareString())
                        PrepareString($Tracks[$i][1]) = PrepareString($Tracks[$x][1]) AND _     ;compare artist
                        $i <> $x Then                                                           ;make sure that we aren't comparing the song with itself
                $foundSwitch = True
                For $y = 1 To UBound($Found)-1
                    If $Found[$y][0] = $x Or $Found[$y][1] = $x Then
                        $foundSwitch = False
                If $foundSwitch = True Then ;if we haven't already recorded the song as a duplicate, then record it
                    $Found[$foundCount][0] = $x
                    $Found[$foundCount][1] = $i
                    $foundCount += 1
                    ReDim $Found[$foundCount+1][2]
                    GUICtrlCreateListViewItem($Tracks[$i][0] & "|" & $Tracks[$i][1] & "|" & $iTracks.Item($i).Location, $List1) ;create a new item
                    _GUICtrlListView_SetItemChecked($List1, $listcount, True) ;set it checked by default
                    $listcount += 1
                    $SpaceSaved += $Tracks[$i][2] ;keep track of the total size that could be saved
    GUICtrlSetData($Scan, "Completed Scan")
    MsgBox(0,"","Scan Complete. Possible space saved: " & Round(($SpaceSaved/1024/1024),2) & " MB")

Func Delete()
    $SpaceSaved = 0
    $count = 0
    For $i = 1 To $foundCount-1 ;for each item in the listview
        If _GUICtrlListView_GetItemChecked($List1, $i-($count+1)) Then ;if the current item is checked, proceed
            FileDelete($iTracks.ItemByName($Tracks[$Found[$i][1]][0]).Location) ;delete the file
            $iTracks.ItemByName($Tracks[$Found[$i][1]][0]).Delete ;delete the library entry
            _GUICtrlListView_DeleteItem($List1, $i-($count+1)) ;delete it from the listview
            $SpaceSaved += $Tracks[$Found[$i][1]][2] ;keep track of how much space the user will save
            $count += 1 ;keep track of how many files have been deleted
    ;display final message
    MsgBox(0,"","Task Complete. You have deleted " & $count & " files, and saved " & Round(($SpaceSaved/1024/1024),2) & " MB of space.")

Func OnAutoItExit()
    $oiTunes = 0 ;destroy iTunes object

Func PrepareString($str) ;removes spaces, quotes, dashes, changes to lowercase (for insensitive case and good comparison)
    Return StringLower(StringStripWS(StringReplace(StringReplace($str,"-",""), "'", ""),8))



Awaiting Diablo III..

Share this post

Link to post
Share on other sites

Saved me 2048MB thanks Kurt!

[center][font="Arial"]If practise makes perfect and no-ones perfect whats the point of practise?[/font]Sorry for my rude attitude when I started here.[/center]

Share this post

Link to post
Share on other sites

Thanks for sharing! :)

AutoIt.4.Life Clubrooms - Life is like a Donut (secret key)

Make sure brain is in gear before opening mouth!
Remember, what is not said, can be just as important as what is said.


What is the Secret Key? Life is like a Donut

If I put effort into communication, I expect you to read properly & fully, or just not comment.
Ignoring those who try to divert conversation with irrelevancies.
If I'm intent on insulting you or being rude, I will be obvious, not ambiguous about it.
I'm only big and bad, to those who have an over-active imagination.

I may have the Artistic Liesense ;) to disagree with you. TheSaint's Toolbox (be advised many downloads are not working due to ISP screwup with my storage)


Share this post

Link to post
Share on other sites

didn't iTunes have that built-in already ?

Anyway good work!

Some Projects:[list][*]ZIP UDF using no external files[*]iPod Music Transfer [*]iTunes UDF - fully integrate iTunes with au3[*]iTunes info (taskbar player hover)[*]Instant Run - run scripts without saving them before :)[*]Get Tube - YouTube Downloader[*]Lyric Finder 2 - Find Lyrics to any of your song[*]DeskBox - A Desktop Extension Tool[/list]indifference will ruin the world, but in the end... WHO CARES :P---------------http://torels.altervista.org

Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this