Skip to content

Instantly share code, notes, and snippets.

Created September 3, 2014 03:48
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/7459361ddfbaed858e46 to your computer and use it in GitHub Desktop.
Save anonymous/7459361ddfbaed858e46 to your computer and use it in GitHub Desktop.
Takes a directory full of disordered, misnamed, obfuscated multi-volume RAR files and extracts them. For those Usenet full TV season backlog posts that get picked up by Sick Beard and have millions of .0 .1 .2 files you can't extract and throw "There are no videofiles in folder" in the post-processor. See e.g. http://sickbeard.com/forums/viewtop…
#!/usr/bin/env ruby
require 'pty'
require 'expect'
$rar_divider = "-------------------------------------------------------------------------------\n"
def check_rar_contents(file)
$stderr.puts "Checking RAR contents for: #{file}"
rar_contents = `unrar l -v "#{file}" 2>&1`.split($rar_divider)
# if there's multiple files in each volume and the file of interest isn't the first,
# would need to modify this to split/iterate on \n first
contained_filename = rar_contents[1].split(' ').first
volume = rar_contents.last.scan(/volume (\d+)\n\n/).flatten.first.to_i
next_volume = rar_contents.last.scan(/Cannot find volume (.+?)\n/).flatten.first
return [contained_filename, volume, next_volume]
end
file_types = {}
Dir.foreach('.') do |file|
$stderr.puts "Checking file type for: #{file}"
file_types[file] = `file "#{file}"`
end
file_volumes = {}
file_types.select{|file,type| type =~ /^#{Regexp.escape(file)}: RAR archive data,/}.each do |file, type|
contained_filename, volume, next_volume = check_rar_contents(file)
file_volumes[contained_filename] ||= {}
file_volumes[contained_filename][volume] = [file, next_volume]
end
file_volumes.each do |filename,volumes|
$stderr.puts filename
$stderr.puts volumes.keys.max
(1..volumes.keys.max).each do |volume|
$stderr.puts "\t#{volume}\t#{volumes[volume].inspect}"
if (!volumes[volume][1].nil?) && File.exist?(volumes[volume][1])
abort "Next file exists!"
end
end
$expect_verbose = true
current_volume = 1
PTY.spawn("unrar x -vp \"#{volumes[1][0]}\" 2>&1") do |unrar_out, unrar_in, pid|
while (current_volume < volumes.keys.max) do
unrar_out.expect(/\[Q\]uit/) do |r|
$stderr.puts "Disk prompt"
contained_filename, current_volume, next_volume = check_rar_contents(volumes[current_volume][0])
$stderr.puts `ln -sfv "#{volumes[current_volume + 1][0]}" "#{next_volume}"`
volumes[current_volume + 1][0] = next_volume
unrar_in.print("C\n")
current_volume += 1
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment