Текстовый редактор, управляемый переименование файлов в Ruby


Я написал следующий скрипт на Ruby несколько лет назад и уже используют его часто до сих пор.

Он открывает текстовый редактор с список файлов в текущем каталоге. Затем вы можете редактировать имена файлов в виде текста. После того, как вы сохраните и закройте файлы будут переименованы.

На переименование позволило мне сохранить таблицу как имена файлов, благодаря мощной колонки возможности редактирования ви (все те).

Вот как один из таких каталогов выглядит так:

enter image description here

Я хотел бы использовать его как пример для практикума, рубиновый. Не могли бы вы, пожалуйста, предложите лучшие практики и улучшен дизайн шаблон?

#!/usr/bin/ruby

RM = '/bin/rm'
MV = '/bin/mv'

from = Dir.entries('.').sort; from.delete('.'); from.delete('..')
from.sort!

from.delete_if {|i| i =~ /^\./} # Hidden files

tmp = "/tmp/renamer.#{Time.now.to_i}.#{(rand * 1000).to_i}"

File.open(tmp, 'w') do |f|
  from.each {|i| f.puts i}
end

ENV['EDITOR'] = 'vi' if ENV['EDITOR'].nil?
system("#{ENV['EDITOR']} #{tmp}")

to = File.open(tmp) {|f| f.readlines.collect{|l| l.chomp}}
`#{RM} #{tmp}`

if to.size != from.size
  STDERR.puts "renamer: ERROR: number of lines changed"
  exit(1)
end

from.each_with_index do |f, i|
  puts `#{MV} -v --interactive "#{f}" "#{to[i]}"` unless f == to[i]
end


496
10
задан 6 февраля 2011 в 06:02 Источник Поделиться
Комментарии
2 ответа

RM = '/bin/rm'
MV = '/bin/mv'

В целом предпочтительно использовать пакета fileutils класса , а не полагаться на утилиты. Хотя в данном конкретном случае, вы можете придерживаться по крайней мере с МВ с пакета fileutils.МВ метод не имеет :интерактивный вариант.


tmp = "/tmp/renamer.#{Time.now.to_i}.#{(rand * 1000).to_i}"

Рубин имеет Tempfile класс , который может создать уникальный временный файл более надежно, чем этот. Вы должны использовать его.


from.each {|i| f.puts i}

Вызов кладет на массив будет добавляет каждую строку по отдельности, так что выше может быть сокращен до Ф.ставит из.


ENV['EDITOR'] = 'vi' if ENV['EDITOR'].nil?

Может быть сокращен до ОКР['редактор'] ||= 'ви'. Хотя то, что вы не особо многословны, так что не важно, что вы выберете.


system("#{ENV['EDITOR']} #{tmp}")

Использовать систему(ОКР[редактор], ТМП) вместо. Таким образом, вы избавиться от интерполяции строк и код по-прежнему работает, если ОКР['редактор'] или ТМП должны содержать пробелы или другие оболочки мета-характер (не то, что они особенно склонны, но это хорошая идея, чтобы использовать несколько аргументов-виде системы , где это возможно).


to = File.open(tmp) {|f| f.readlines.collect{|l| l.chomp}}

Как правило, это может быть заменен на = файл.readlines(ТМП).собирать {|л| л.гусеничка}. Однако если вы будете следовать мое предложение использовать Tempfile, что не вариант больше.


`#{RM} #{tmp}`

Если вы используете пакета fileutils, это будет только пакета fileutils.РМ(ТМП) (или РМ(ТМН) если вы включаете пакета fileutils). Если вы не хотите использовать пакета fileutils, вы должны по крайней мере использовать системы(РМ, ТМП) по тем же причинам, что и выше.

Однако, если вы использовать Tempfile, что вы должны, это будет излишним в любом случае.


from.each_with_index do |f, i|
puts `#{MV} -v --interactive "#{f}" "#{to[i]}"` unless f == to[i]
end

Перебор двух массивов параллельно использовать молнию:

from.zip(to) do |f, t|
system(MV, "-v", "--interactive", f, t) unless f == t
end

Обратите внимание, что здесь, используя систему вместо обратные кавычки-это особенно важно, так как один из файлов В С или в с пробелами-это вообще-то скорее.


Так со всеми моими предложениями, ваш код теперь должен выглядеть так:

#!/usr/bin/env ruby
require 'tempfile'

MV = '/bin/mv'

from = Dir.glob('*').sort

ENV['EDITOR'] ||= 'vi'

to = nil
Tempfile.open("renamer") do |f|
f.puts from
f.close
system(ENV['EDITOR'], f.path)
f.open
to = f.readlines.collect {|l| l.chomp}
end

if to.size != from.size
STDERR.puts "renamer: ERROR: number of lines changed"
exit(1)
end

from.zip(to) do |f, t|
system(MV, "-v", "--interactive", f, t) unless f == t
end

9
ответ дан 6 февраля 2011 в 04:02 Источник Поделиться

Просто пару вещей:

#!/usr/bin/ruby

Вполне возможно, что на некоторых системах это не там, где рубиновые жизни, это лучше делать:

#!/usr/bin/env ruby


from = Dir.entries('.').sort; from.delete('.'); from.delete('..')

Может быть записан как

from = Dir.entries('.').sort - ['.', '..']

Который является более емким и исключает наличие трех операторов на одной строке (что нельзя делать).

Или вы могли бы устранить скрытые файлы и . / .. на одном дыхании с:

from = Dir.entries(.).select do |filename|
filename[0].chr != '.'
end

Редактировать:

from = Dir.glob("*").sort

Это наверняка лучшее решение.

5
ответ дан 6 февраля 2011 в 07:02 Источник Поделиться