Skip to content

Instantly share code, notes, and snippets.

@henrik
Created May 28, 2010 20:36
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save henrik/417708 to your computer and use it in GitHub Desktop.
Save henrik/417708 to your computer and use it in GitHub Desktop.
Ruby script/command to rename TV series episodes by pattern, e.g. for Plex.
#! /usr/bin/env ruby -r ftools
# "vname" by Henrik Nyh <http://henrik.nyh.se> on 2010-05-28 under the MIT license.
#
# Usage:
#
# vname PATTERN
#
# Prompts to rename files in the working directory matching the PATTERN into this pattern:
#
# X-Files - S01E03 - Pilot.avi
#
# Useful for e.g. renaming TV series episodes for Plex.
#
# The pattern is a combination of whichever of these you like:
#
# :s - season number (defaults to 1)
# :e - episode number (also handles intervals like 01-02, defaults to 1)
# :p - programme/show name
# :t - episode title
# ... - any uninteresting sequence of characters
#
# The pattern doesn't have to match the full filename, only part. Don't mention the extension.
#
# You can use e.g. ":s:e" for "203.avi" to get "S02E03". In that case it assumes the season is a single digit.
#
# You may also specify programme and season explicitly as second and third command-line arguments, to get around
# tricky names. E.g. "tpz-deadwood301.avi" makes it difficult to separate programme and season, so you could do
#
# vname tpz-deadwood3:e Deadwood 3
#
# Example session:
#
# $ touch "X-Files [1x01] Pilot- DVDRip.avi"
# $ touch "X-Files [1x02] Ett kul avsnitt- DVDRip.avi"
# $ ls X-Files*
# X-Files [1x01] Pilot- DVDRip.avi X-Files [1x02] Ett kul avsnitt- DVDRip.avi
# $ vname ":p [:sx:e] :t-"
#
# From: X-Files [1x01] Pilot- DVDRip.avi
# To: X-Files - S01E01 - Pilot.avi
#
# From: X-Files [1x02] Ett kul avsnitt- DVDRip.avi
# To: X-Files - S01E02 - Ett kul avsnitt.avi
#
# Rename 2 files (y/n - default: n)? y
#
# Renamed: X-Files [1x01] Pilot- DVDRip.avi ==> X-Files - S01E01 - Pilot.avi
# Renamed: X-Files [1x02] Ett kul avsnitt- DVDRip.avi ==> X-Files - S01E02 - Ett kul avsnitt.avi
#
# Done.
# $ ls X-Files*
# X-Files - S01E01 - Pilot.avi X-Files - S01E02 - Ett kul avsnitt.avi
# Usage instructions.
if ARGV.empty?
puts File.readlines(__FILE__).grep(/^# /)
exit
end
pattern = ARGV[0]
global_programme = ARGV[1]
global_season = ARGV[2]
patterns = pattern.split(/(:[pest]|\.\.\.)/u)
parts = patterns.map { |part|
case part
when ':p': /(.+)/
when ':e': /(\d+(?:-\d+)?)/
when ':s': /(\d+?)/
when ':t': /(.+)/
when '...': /.*/
else Regexp.escape(part)
end
}
parts << /.*(\.\w+)$/ # Extension.
re = parts.join
capture_groups = patterns.select { |part| part.match(/:[pest]/) }
renamings = []
filenames = Dir["*"]
filenames.each do |old_filename|
next unless (match = old_filename.match(re))
captures = match.captures
extension = captures.pop
mapping = captures.to_enum.with_index.inject({}) {|hash, (value, index)| hash.merge( capture_groups[index] => value ) }
programme, episode, season, title = mapping.values_at(*%w[:p :e :s :t])
programme = global_programme || programme
season = global_season || season
new_filename_parts = []
new_filename_parts << programme
new_filename_parts << format("S%02dE%02d", (season ? season.to_i : 1), (episode ? episode.to_i : 1))
new_filename_parts << title
new_filename = new_filename_parts.compact.join(' - ') + extension
renamings << [old_filename, new_filename]
puts
puts "From: #{old_filename}"
puts "To: #{new_filename}"
end
if renamings.empty?
puts "Nothing matches that pattern."
else
puts
print "Rename #{renamings.length} file#{'s' if renamings.length > 1} (y/n - default: n)? "
answer = STDIN.gets
exit unless answer.match(/y/i)
puts
renamings.each do |old_filename, new_filename|
File.mv(old_filename, new_filename)
puts "Renamed: #{old_filename} ==> #{new_filename}"
end
puts
puts "Done."
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment