iTunes - Deleting Albums From Smart Playlists

August 2, 2007

Easily the most annoying thing about Smart Playlists is that you can’t modify your Library through them. So you just added a new album and you find it from Recently Added (an incredibly useful playlist IMHO), but the album turns out to be crap. Now you have to find that tune from the Library, select it and all the other from that album and delete them. Or just write a script to do it for you:

tell application "iTunes"

      set theAlbum to album of the selection as string
      set theArtist to artist of the selection as string

      tell playlist 1 of source 1

        set albumTracks to every track whose (album = theAlbum and artist = theArtist)
        set thePath to POSIX path of (location of item 1 of albumTracks as string)
        set foldPath to POSIX file (do shell script "dirname " & quoted form of thePath) as string
        tell application "Finder" to move foldPath to the trash
        delete (every track whose (album = theAlbum and artist = theArtist))

      end tell

end tell

AppleScript’s variable referencing is still a bit of a mystery to me (and it is rather late) so I have no idea why delete albumTracks (a list) doesn’t work, while saying every track whose (album = theAlbum and artist = theArtist) (also a list) twice does. Doing the search twice slows the script down quite a bit, so if you know the reason, please leave it in the comments. ;)

UPDATE

HAS comments:

every track whose (album = theAlbum and artist = theArtist) (also a list)

That’s a reference literal, not a list. An AppleScript ‘reference’ is really a query: nothing happens until it gets used in a command - ‘get’, ‘set’, ‘move’, ‘delete’, etc. Kinda like XPath queries over XML-RPC, rather than COM/DOM/CORBA.

If a reference literal appears as a parameter to an explicit application command, e.g.:

    delete (every track whose (album = theAlbum and artist = theArtist))

it gets sent straight to the application as-is. The application then evaluates the reference and applies the command to the object or objects identified by it.

If you write it in any other context, e.g.:

    set albumTracks to every track whose (album = theAlbum and artist = theArtist)

AppleScript will automatically put it in a ‘get’ event for you and send that. This behind-the-scenes trickery is done for the user’s convenience; the downside is that it makes it harder to understand how application scripting actually works, which is why it’s often mistaken for OOP when it’s not.

So I the last line should simply be written as a loop (for performance reasons):

repeat with aTrack in albumTracks
  delete aTrack
end repeat