2012-05-25 14 views
6

He estado intentando resolver un programa de cambio de nombre basado en ruby, como un ejercicio de programación para mí (estoy al tanto del cambio de nombre en Linux, pero quiero aprender Ruby y cambiar el nombre es no disponible en Mac).Cómo cambiar el nombre de los archivos en ruby ​​en masa

En el código siguiente, el problema es que el método .include? siempre devuelve falso aunque veo que el nombre de archivo contiene dicho patrón de búsqueda. Si hago un comentario sobre la verificación include?, gsub() no parece generar un nuevo nombre de archivo (es decir, el nombre del archivo sigue siendo el mismo). Entonces, ¿alguien puede ver lo que hice mal? ¡Muchas gracias de antemano!

Aquí es el comportamiento esperado: Suponiendo que en la carpeta actual hay tres archivos: a1.jpg, a2.jpg y a3.jpg El script de Ruby debe ser capaz de cambiar su nombre a 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

Lo que de entrada le están proporcionando a las tres indicaciones 'gets'? – bta

+0

Creo seriamente que el comando 'rename' puede hacer mejor en eso ... – texasbruce

+0

@texasbruce, no hay ningún comando de cambio de nombre en mac. tal vez macports tiene algo, pero solo encontró un montón de scripts Perl. Pero como sugerí antes, es un ejercicio de rubí para mí – Antony

Respuesta

9

versión ligeramente modificada:

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 

diferencias clave:

  • Utilice .strip para eliminar la línea nueva que sale de gets. De lo contrario, este carácter de nueva línea estropeará todos tus intentos de coincidencia.
  • Utilice el patrón de búsqueda proporcionado por el usuario en la llamada glob en lugar de englobar todo y luego filtrarlo manualmente más tarde.
  • Utilice entry (es decir, el nombre completo del archivo) en las llamadas a gsub y rename en lugar de origin. origin realmente solo es útil para la prueba .include?. Como es un fragmento de un nombre de archivo, no se puede usar con rename. Eliminé la variable origin por completo para evitar la tentación de hacer un mal uso de ella.

Para su ejemplo de estructura de carpetas, entrando *.jpg, a y b para las tres indicaciones de entrada (respectivamente) debería cambiar el nombre de los archivos que usted está esperando.

+0

¡Ahh! Gracias por la explicación. Al menos de la documentación (ruby-doc.org), parece mostrar esa tira (elimina los espacios blancos iniciales y finales), y chomp (quita las líneas nuevas), así que terminé con gets.chomp.strip con suerte no es exagerado . De todos modos, el script funciona a la perfección! – Antony

+0

@ Antony- Las nuevas líneas son parte de lo que Ruby considera "espacios en blanco", por lo tanto, tanto 'chomp' como' strip' son redundantes. 'strip' hace todo lo que' chomp' hace, más más. – bta

2

Su problema es que gets devuelve una nueva línea al final de la cadena. Entonces, si escribe "foo", entonces searchPattern se convierte en "foo\n". La solución más simple es:

searchPattern = gets.chomp 

podría reescribir ligeramente su código:

$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

Gracias por señalar chomp. Aprendiendo algo nuevo cada día. – Antony

+0

¿Dónde se establece el argumento "new_path" que está enviando a File.rename? ¿Tal vez quiso decir File.rename (file, new_name) en su lugar? De lo contrario, le daría esto +1 – emery

3

Utilicé la respuesta aceptada para corregir un grupo de nombres de archivos copiados.

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

Aquí hay una versión corta que he usado hoy (sin coincidencia de patrones)

Guardar este archivo como rename.rb y ejecutarlo en el interior del símbolo del sistema con rubí cambiar el nombre.rb

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

que tenía/Copia del _MG_2435.JPG convierte en car1, car2, ...

Cuestiones relacionadas