Geoffrey Wiseman

Renaming Looney Tunes

Say you happened to have a whole bunch of classic Looney Tunes episodes, say about 175 of them, but they don't conform to the naming standards that Plex uses to organize them and download metadata.

You'd like to get these files into Plex. The simplest way to do that is to rename them, by hand. In order to do that, you could search for the episode by title on TheTVDB.com's index of all Looney Tunes episodes. That's not a terrible approach for a few files, but it's time-consuming, error-prone and, frankly, dull. You could do five a day, but that's still 35 days of drudgery.

So, what else can you do? Well, you could sign up for an API key from TheTVDB. You can use that to download the series data. There are ruby gems (tvdbr, tvdb) for interacting with TheTVDB, and they might make your life easier, but the API gets you a big XML file that just isn't that hard to process without an API for a one-off job.

So if you wanted to rename a bunch of TV shows for Plex using TheTVDB's database, you could do something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
require 'rexml/document'

def parse_document( doc )
  mapping = Hash.new
  doc.elements.each( "Data/Episode" ) do |episode|
    episode_name = episode.elements["EpisodeName"].text
    stripped = strip_to_letters( episode_name )
    season_no = episode.elements["SeasonNumber"].text
    episode_no = episode.elements["EpisodeNumber"].text.rjust(2,"0")
    fname = "Looney Tunes - s#{season_no}e#{episode_no}"
    mapping[stripped] = fname
  end
  return mapping
end

def strip_to_letters( input )
    input.gsub( /\W/, "" ).downcase
end

def rename_files( mapping, path )
  Dir.glob( "#{path}/**/*.avi" ) do |file|
    ext = File.extname( file )
    basename = File.basename( file, ext )
    dir = File.dirname( file )
    match = /\d\d - (.+)/.match( basename )
    rename_file( mapping, dir, basename, ext, match ) unless match.nil?
  end
end

def rename_file( mapping, dir, basename, ext, match )
  stripped = strip_to_letters( match[1] )
  if mapping.has_key? stripped then
    new_name = "#{mapping[stripped]} - #{match[1]}#{ext}"
    puts( "Renaming #{basename}#{ext} to #{new_name} in #{dir}" )
    File.rename( "#{dir}/#{basename}#{ext}", "#{dir}/#{new_name}" )
  else
    puts( "Can't find mapping for: #{basename} (#{stripped})")
  end
end

file = File.new( "looney.xml" )
doc = REXML::Document.new file
mapping = parse_document( doc )
rename_files( mapping, "media/looney-tunes-collection" )

There were some failed matches -- cases where the filename's letters didn't exactly match the titles in TheTVDB. For this number of cases, fixing a few by hand seemed like the best tradeoff. A fuzzy text matching library (e.g. blurrily, fuzzy-string-match) might have solved those cases automatically.

This is a one-off script written in the evening. I'm sure it could be improved. I just figure that sharing it might make someone's life / hobby / leisure time slightly easier.