Last active
January 11, 2018 03:27
-
-
Save elomatreb/41d023d0939b9743deb6ad1b9bc39322 to your computer and use it in GitHub Desktop.
Renaming script I use for managing episodes of downloaded series batches
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require "fileutils" | |
require "highline" | |
# Characters illegal in most filenames | |
ILLEGAL_CHARS = %w[< > : " / \\ | * ?] | |
cli = HighLine.new | |
files = ARGV.select {|f| File.file? f }.freeze | |
files.each do |f| | |
next if File.basename(f) == f | |
warn "'#{f}' is not the same as its basename, aborting. (Not in current directory?)" | |
exit 1 | |
end | |
puts HighLine.color("Processing #{files.size} files", :green) | |
# Set the prefix, typically the show name | |
prefix = cli.ask("Prefix (show name)? ") do |q| | |
q.validate = lambda do |a| | |
a.match?(/\A[[:print:]]+\z/) && !a.match?(Regexp.union(ILLEGAL_CHARS)) | |
end | |
q.readline = true | |
q.responses[:not_valid] = "The prefix may not contain illegal characters (#{ILLEGAL_CHARS.join(", ")})" | |
end | |
# Get the season (or disable) | |
season = cli.ask("Season (Leave empty for no season)? ") do |q| | |
q.validate = -> (a) { a == "" || a.to_i > 0 } | |
q.readline = true | |
q.answer_type = -> (a) { a == "" ? nil : Integer(a, 10) } | |
q.responses[:not_valid] = "You must enter a positive integer (> 0) or leave this empty." | |
end | |
puts "-------\n\n" | |
new_filenames = files.map do |f| | |
puts "Processing file: '#{HighLine.color(f, :bold)}'" | |
guessed_id = f.match(/S?\d+E(\d+)/i) {|m| Integer(m[1], 10) rescue nil } || | |
f.match(/(\d\d)/) {|m| Integer(m[1], 10) rescue nil } | |
episode_id = cli.ask(" Episode ID? ") do |q| | |
# Either single digit (will be padded), double digit, or double-episode with | |
# two double-digits joined by a &. Supports decimals. | |
q.validate = /\A\d(?:\.\d)?\z|\A\d\d(?:\.\d)?(?:&\d\d(?:\.\d)?)?\z/ | |
q.default = format "%02d", guessed_id | |
q.readline = true | |
q.answer_type = lambda do |a| | |
# Prefix the answer with a 0 if it was given as a single | |
return a unless a.match?(/\A\d(?:\.\d)?\z/) | |
"0" + a | |
end | |
q.responses[:not_valid] = "The episode ID must be in single digit form (D or D.D+), double digit form (DD or DD.D+), or double-double digit form (for double episodes, DD&DD DD.D+&DD.D+). Decimals are optional." | |
end | |
episode_title = cli.ask("Episode title? ") do |q| | |
q.validate = lambda do |a| | |
a.match?(/\A[[:print:]]+\z/) && !a.match?(Regexp.union(ILLEGAL_CHARS)) | |
end | |
q.readline = true | |
q.responses[:not_valid] = "The title may not contain illegal characters (#{ILLEGAL_CHARS.join(", ")})" | |
end | |
puts "-------\n\n" # Separator | |
extension = f[/.*\.(.+?)\z/, 1] # File extension | |
if season | |
format "%s - S%02dE%s - %s.%s", prefix, season, episode_id, episode_title, extension | |
else | |
format "%s - %s - %s.%s", prefix, episode_id, episode_title, extension | |
end | |
end | |
changes = files.zip new_filenames | |
left = [files.map(&:length).max + 1, 10].max | |
right = [new_filenames.map(&:length).max + 1, 5].max | |
puts HighLine.color(" Original ".ljust(left), :bold) + "|" + HighLine.color(" New", :bold) | |
puts "-" * left + "+" + "-" * right | |
puts changes.map {|old, new| old.rjust(left-1) + " → " + new }.join "\n" | |
puts HighLine.color(" → #{changes.select {|new, old| old != new }.size} changes.", :bold, :white) | |
apply = cli.agree(" Apply these changes? [y/n] ") do |q| | |
q.character = :getc | |
end | |
puts # getc doesn't do a proper newline | |
if apply | |
changes.each {|from, to| FileUtils.mv from, to } | |
puts "done." | |
else | |
puts "Not applying; exiting" | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment