2012-05-25 24 views
6

Ho cercato di elaborare un programma di ridenominazione file basato su ruby, come esercizio di programmazione per me stesso (sono consapevole di rinominare sotto linux, ma voglio imparare Ruby e rinominare è non disponibile in Mac).Come rinominare i file in ruby ​​

Dal codice riportato di seguito, il problema è che il metodo .include? restituisce sempre false anche se vedo che il nome del file contiene tale modello di ricerca. Se commento il controllo include?, il numero gsub() non sembra generare un nuovo nome di file (il nome del file rimane invariato). Quindi qualcuno può dare un'occhiata per vedere cosa ho sbagliato? Grazie molte in anticipo!

Qui è il comportamento previsto: Supponendo che nella cartella attuale ci sono tre file: a1.jpg a2.jpg, e a3.jpg Lo script di Ruby dovrebbe essere in grado di rinominarlo in b1.jpg, b2. jpg, b3.jpg

#!/Users/Antony/.rvm/rubies/ruby-1.9.3-p194/bin/ruby 

puts "Enter the file search query" 
searchPattern = gets 
puts "Enter the target to replace" 
target = gets 
puts "Enter the new target name" 
newTarget = gets 
Dir.glob("./*").sort.each do |entry| 
    origin = File.basename(entry, File.extname(entry)) 
    if origin.include?(searchPattern) 
    newEntry = origin.gsub(target, newTarget) 
    File.rename(origin, newEntry) 
    puts "Rename from " + origin + " to " + newEntry 
    end 
end 
+0

Cosa ingresso State fornendo per i tre 'istruzioni gets'? – bta

+0

Credo seriamente che il comando "rename' possa fare meglio in questo ... – texasbruce

+0

@texasbruce, non esiste un comando di rinomina in mac. forse i Macport hanno qualcosa, ma hanno trovato solo un sacco di script perl. Ma come ho suggerito prima, è un esercizio rubino per me – Antony

risposta

9

versione leggermente modificata:

puts "Enter the file search query" 
searchPattern = gets.strip 
puts "Enter the target to replace" 
target = gets.strip 
puts "Enter the new target name" 
newTarget = gets.strip 
Dir.glob(searchPattern).sort.each do |entry| 
    if File.basename(entry, File.extname(entry)).include?(target) 
    newEntry = entry.gsub(target, newTarget) 
    File.rename(entry, newEntry) 
    puts "Rename from " + entry + " to " + newEntry 
    end 
end 

differenze chiave:

  • Utilizzare .strip per rimuovere il newline finale ottenuto da gets. Altrimenti, questo carattere di nuova riga rovinerà tutti i tuoi tentativi di corrispondenza.
  • Utilizzare il modello di ricerca fornito dall'utente nella chiamata glob anziché globbing per tutto e quindi filtrarlo manualmente in seguito.
  • Utilizzare entry (ovvero il nome file completo) nelle chiamate a gsub e rename anziché origin. origin è davvero utile solo per il test .include?. Poiché si tratta di un frammento di un nome file, non può essere utilizzato con rename. Ho rimosso completamente la variabile origin per evitare la tentazione di utilizzarla in modo improprio.

Per la vostra struttura di cartelle ad esempio, entrando *.jpg, a, e b per le tre richieste di ingresso (rispettivamente) dovrebbero rinominare i file come vi aspettate.

+0

Ahh! Grazie per la spiegazione. Almeno dalla documentazione (ruby-doc.org), sembra che mostri quella striscia (rimuove gli spazi bianchi iniziali e finali) e chomp (rimuove le nuove righe), così ho finito con gets.chomp.strip Spero che non sia eccessivo . Ad ogni modo la sceneggiatura funziona perfettamente! – Antony

+0

@ Antony- Le newline fanno parte di ciò che Ruby considera "spazio bianco", quindi è necessario ridimensionare sia 'chomp' che' strip'. 'strip' fa tutto ciò che fa 'chomp', e molto altro. – bta

2

tuo problema è che gets restituisce una nuova riga alla fine della stringa. Quindi, se digiti "foo", allora searchPattern diventa "foo\n". La correzione più semplice è:

searchPattern = gets.chomp 

potrei riscrivere un po 'il tuo codice:

$stdout.sync 
print "Enter the file search query: "; search = gets.chomp 
print "Enter the target to replace: "; target = gets.chomp 
print " Enter the new target name: "; replace = gets.chomp 
Dir['*'].each do |file| 
    # Skip directories 
    next unless File.file?(file) 
    old_name = File.basename(file,'.*') 
    if old_name.include?(search) 
    # Are you sure you want gsub here, and not sub? 
    # Don't use `old_name` here, it doesn't have the extension 
    new_name = File.basename(file).gsub(target,replace) 
    File.rename(file, new_path) 
    puts "Renamed #{file} to #{new_name}" if $DEBUG 
    end 
end 
+0

Grazie per aver sottolineato chomp. Imparare qualcosa di nuovo ogni giorno. – Antony

+0

Dove è impostato l'argomento "new_path" che stai inviando in File.rename? Forse intendevi invece File.rename (file, new_name)? Altrimenti, darei questo +1 – emery

3

Ho usato la risposta accettata per correggere un gruppo di nomi di file copiati.

Dir.glob('./*').sort.each do |entry| 
    if File.basename(entry).include?(' copy') 
    newEntry = entry.gsub(' copy', '') 
    File.rename(entry, newEntry) 
    end 
end 
0

Ecco una versione corta che ho usato oggi (senza pattern matching)

Salva questo file come rename.rb ed eseguire all'interno del prompt dei comandi con rubino rinominare.rb

count = 1 
newname = "car" 
Dir["/path/to/folder/*"].each do |old| 
    File.rename(old, newname + count.to_s) 
    count += 1 
end 

ho avuto/Copia del _MG_2435.JPG convertito in car1, car2, ...