Skip to content

Instantly share code, notes, and snippets.

@indirect
Created December 19, 2008 00:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save indirect/37739 to your computer and use it in GitHub Desktop.
Save indirect/37739 to your computer and use it in GitHub Desktop.
TV Show file renamer and sorter
# TV show renamer/sorter script
# Call with directories to sort from and to:
# autosorter.rb 'Downloads/Completed' 'Video/TV Shows'
NAME_FORMATS = [
/^(.+?) S(\d\d)E(\d\d(?:-E\d\d)?)(.*?)(?: (?:\wDTV|PROPER|WS).*)? (...)$/i, # S00E00 format
/^(.+?) (\d?\d)x(\d\d(?:-\d\d)?)(.*?)(?: (?:\wDTV|PROPER|WS).*)? (...)$/i # 00x00 format
]
class String
def spaceify
self.gsub(/\.(\S)/, ' \1')
end
def parse_show_name
NAME_FORMATS.each do |format|
md = self.spaceify.match(format)
return md if md
end
return nil
end
def titlecase
# from http://github.com/michaelboutros/titlecase
small_words = %w(a an and as at but by en for if in of on or the to via vs. vs v v.)
special_characters = %w(- ^)
string = self.split
string.map! do |word|
word.strip!
if [string.first, string.last].include?(word) then word.capitalize! end
next(word) if small_words.include?(word)
next(word) if special_characters.include?(word)
next(word) if word =~ /[A-Z]/
word = begin
unless (match = word.match(/[#{special_characters.to_s}]/))
word.sub(/\w/) { |letter| letter.upcase }
else
word.split(match.to_s).map! {|word| word.capitalize }.join(match.to_s)
end
end
end
string.join(' ')
end
end
def sort_directory(from_dir, to_dir)
cmds = []
listing = Dir[File.join(from_dir, '*')]
# Test cases
# listing = [
# "/Complete/Dexter.s02e03.avi",
# "/Complete/Gossip Girl 1x12 Something or other.mkv",
# "/Complete/dexter 02x04.avi",
# "/Complete/terminator.the.sarah.connor.chronicles.s02e06.720p.hdtv.x264-ctu.mkv",
# "/Complete/The.IT.Crowd.S03E04.WS.PDTV.XviD-ORGANiC.[VTV].avi",
# "/Complete/something that is not a tv show",
# "/Complete/Sanctuary US S01E02.avi",
# "/Complete/Sanctuary.S01E01-E02.720p.HDTV.X264-0TV.mkv"
# ]
matches = listing.map do |n|
fn = File.basename(n)
[fn, *fn.parse_show_name]
end
shows = matches.map do |oname, match, show, sn, en, ename, ext|
if match
cleaned_name = "#{show} #{sn.to_i}x#{en.sub('E','')}"
cleaned_name << " #{ename}" if ename.size > 0
cleaned_name = cleaned_name.titlecase
cleaned_name << ".#{ext}"
show_dir = File.join(to_dir, show, "#{show} Season #{sn.to_i}")
[oname, cleaned_name, show_dir]
else
nil
end
end
shows.compact.each do |original_name, cleaned_name, show_dir|
cmds << %{mkdir -p "#{show_dir}"} unless File.exist?(show_dir)
cmds << %{mv "#{File.join(from_dir, original_name)}" "#{File.join(show_dir, cleaned_name)}"}
end
cmds.each do |c|
puts(c)
system(c)
sleep 1
end
end
if (__FILE__ == $0)
unless ARGV.size == 2
puts "Call with directories to sort from and to:"
puts " autosort.rb 'Downloads/Completed' 'Video/TV Shows'"
else
puts "autosorting from '#{ARGV[0]}' to '#{ARGV[1]}'..."
loop do
sort_directory(ARGV[0], ARGV[1])
sleep 300
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment