2012-05-25 5 views
6

Я пытался разработать программу переименования файлов на основе ruby, как упражнение для программирования для себя (мне известно о переименовании под Linux, но я хочу узнать Ruby и переименовать недоступен в Mac).Как массовое переименование файлов в ruby ​​

Из приведенного ниже кода проблема заключается в том, что метод .include? всегда возвращает значение false, хотя я вижу, что имя файла содержит такой шаблон поиска. Если я прокомментирую проверку include?, gsub(), похоже, вообще не генерирует новое имя файла (то есть имя файла остается неизменным). Так может кто-нибудь, пожалуйста, посмотрите, что я сделал неправильно? Спасибо за кучу заранее!

Вот ожидаемое поведение: Предполагая, что в текущей папке есть три файла: a1.JPG, A2.jpg и a3.jpg Сценарий рубин должен быть в состоянии переименовать его в 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

Какой вклад вы обеспечение для трех 'gets' подсказками? – bta

+0

Я серьезно думаю, что команда 'rename' может сделать лучше в этом ... – texasbruce

+0

@texasbruce, в mac нет команды rename. возможно, у macports есть что-то, но только нашел кучу perl-скриптов. Но, как я уже говорил ранее, это упражнение для рубинов для меня – Antony

ответ

9

Слегка измененная версия:

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 

Основные отличия:

  • Используйте .strip чтобы удалить завершающую строку перевода, которую вы получаете из gets. В противном случае этот символ новой строки испортит все ваши попытки совпадения.
  • Используйте шаблон поиска для пользователя в вызове glob вместо того, чтобы подбирать все, а затем вручную фильтровать его позже.
  • Используйте entry (то есть, полное имя файла) в телефонных звонках gsub и rename вместо origin. origin действительно полезен только для теста .include?. Поскольку это фрагмент имени файла, он не может использоваться с rename. Я полностью удалял переменную origin, чтобы избежать соблазна использовать ее неправильно.

Для вашей структуры примера папки, введя *.jpg, a и b для трех входных запросов (соответственно) должен переименовать файлы, как вы ожидаете.

+0

Ahh! Спасибо за объяснение. По крайней мере, из документации (ruby-doc.org), похоже, что эта полоса (удаляет ведущие и завершающие пробелы) и chomp (удаляет новые строки), поэтому я попал в get.chomp.strip. Надеюсь, это не перебор. , В любом случае скрипт работает отлично! – Antony

+0

@ Antony-Newlines - это часть того, что Ruby считает «пробелами», поэтому «chomp» и «strip» являются излишними. 'strip' делает все, что' chomp' делает, плюс больше. – bta

2

Ваша проблема заключается в том, что gets возвращает новую строку в конце строки. Итак, если вы наберете «foo», то searchPattern станет "foo\n". Самое простое исправление:

searchPattern = gets.chomp 

Я мог бы немного переписать код:

$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

Благодарим за указание на chomp. Изучайте что-то новое каждый день. – Antony

+0

Где находится аргумент «new_path», который вы отправляете в файл. Возможно, вы имели в виду File.rename (file, new_name)? В противном случае, я бы дал это +1 – emery

3

Я использовал принятый ответ, чтобы исправить кучу названий копируемых файлов.

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

Вот короткая версия Я использовал сегодня (без сопоставления с образцом)

Сохранить это как rename.rb файл и запустить его в командной строке с рубин переименовывать.гь

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

Я имел/Копия _MG_2435.JPG превращается в car1, car2, ...

Смежные вопросы