jeudi, décembre 21, 2006

Renommer ses divx en ruby

On m'a mis au défit de faire un script pour renommer un ensemble de divx dont le nom de fichier ressemble à [qqchose]01[autrechose]02[encore_qqchose].[une_extension]:
require 'ftools'
require 'fileutils'

from_directory = "divx"
to_directory = "divx_renamed"
extentions = %w{.srt .avi .mov .wmv}
prefix = "lost"
pattern = /[0-9]{2}/

Dir.mkdir(to_directory) unless File.exist?(to_directory)

Dir.foreach(from_directory) do |filename|
  fullpath = from_directory + '/' + filename
  file_ext = File.extname(fullpath)
  if (File.file?(fullpath) && extentions.include?(file_ext))
    puts "Changing: " + filename + "..."
    # *[0-9]{2}*[0-9]{2}.ext
    basename =  File.basename(fullpath, file_ext)
    basename =~ pattern
    season = $&
    # match against the rest of the basename
    $' =~ pattern
    episode = $&
    new_basename = prefix + "-s" + season + "-e" + episode
    puts new_basename
    File.copy fullpath, to_directory + '/' + new_basename + file_ext
  end
end
Si vous avez des idées pour le rendre plus court (mais toujours lisible)... les commentaires sont les bienvenus ;)
Technorati tags:

5 commentaires:

Sebz a dit…

C'est beau Ruby ! :)
Promis je m'y mets !!

pH a dit…

On peut aussi capturer la saison et le numero de l'episode avec une seule regexp, je crois !

En plus, j'ai tendance à préférer les méthodes de MatchData plutôt que les variables en dollar à la Perl ...

------------------------------
require 'ftools'
require 'fileutils'

from_directory = "divx"
to_directory = "divx_renamed"
extentions = %w{.srt .avi .mov .wmv}
prefix = "lost"

# Et pourquoi pas un pattern pour toutes la ligne ??
# Notes les parenthèses autour des regexp qui permettent de
# capturer le numéro de la saison et celui de l'episode ...
pattern = /.*([0-9]{2}).*([0-9]{2}).*/

Dir.mkdir(to_directory) unless File.exist?(to_directory)

Dir.foreach(from_directory) do |filename|
fullpath = from_directory + '/' + filename
file_ext = File.extname(fullpath)
if (File.file?(fullpath) && extentions.include?(file_ext))
puts "Changing: " + filename + "..."
# *[0-9]{2}*[0-9]{2}.ext
basename = File.basename(fullpath, file_ext)

m = pattern.match(basename)

# m est un objet de type MatchData, dans lequel m[0] est la
l'expression complete, m[1] est ce qui est capturé par le premier groupe
de parenthese, m[2] par le second, etc ...

season = m[1]
episode = m[2]
new_basename = prefix + "-s" + season + "-e" + episode
puts new_basename
File.copy fullpath, to_directory + '/' + new_basename + file_ext
end
end
-------------------

J a dit…

On peut surtout éviter de sélectionner des fichiers dont on ne veut pas. On peut aussi se servir des opérateurs que Ruby met à notre disposition.

J'aurais tout simplement écrit :
---------------------------------------
require 'ftools'

from_directory = "foobar"
to_directory = "fooqux"
extentions = ['srt','avi','mov','wmv']
prefix = "lost"

Dir.mkdir(to_directory) unless File.exist?(to_directory)

Dir[from_directory + "/*[0-9][0-9]*[0-9][0-9].{#{extentions.join(',')}}"].each do |filename|
puts "Changing: #{filename}..."
puts(filename, (to_directory + '/' + prefix + "-s%s-e%s" % filename.scan(/[0-9]{2}/)) + File.extname(filename))
end
--------------------------------

...ce qui fait exactement la même chose, mais en nettement plus simple, et en carrément plus lisible aussi, non ?



Maintenant, bien que je sois un immense fan de Ruby, j'aime utiliser l'outil le plus approprié, et dans ce cas précis, l'outil approprié, c'est le shell. Un utilisateur de zsh tapera tout simplement sur sa ligne de commande :
zmv '*(<0-9><0-9>)*(<0-9><0-9>).(avi|wmv|mov|srt)' 'lost-s$1-e$2.$3'

...ce qui fait exactement la même chose, en encore plus simple.

J a dit…

Enfin, il faut remplacer le deuxième puts par un File.copy. Vous aurez corrigé de vous-même ^^

Benjamin Francisoud a dit…

Cool un exemple plus court! Interessant j'apprend des trucs...

Oui le "unless" je m'y suis m'y depuis peu... (un peu de mal à perdre les vieille habitudes java)

Zsh oui ca marche très bien aussi si on est sous linux :p