Ruby показывает прогресс при копировании файлов

Я хотел бы иметь возможность показать ход операции копирования файлов при копировании файлов с помощью Ruby (в настоящее время с помощью FileUtils.cp). Я пытался установить для параметра verbose значение true, но это, похоже, просто показывает мне выданную команду копирования.

В данный момент я запускаю этот скрипт из командной строки, поэтому в идеале я хотел бы иметь возможность представить что-то вроде того, что делает SCP, когда он копирует файлы, но я не слишком беспокоюсь о презентации, пока я вижу прогресс .


person DEfusion    schedule 19.03.2009    source источник


Ответы (4)


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

require 'rubygems'
require 'progressbar'

in_name     = "src_file.txt"
out_name    = "dest_file.txt"

in_file     = File.new(in_name, "r")
out_file    = File.new(out_name, "w")

in_size     = File.size(in_name)
# Edit: float division.
batch_bytes = ( in_size / 100.0 ).ceil
total       = 0
p_bar       = ProgressBar.new('Copying', 100)

buffer      = in_file.sysread(batch_bytes)
while total < in_size do
 out_file.syswrite(buffer)
 p_bar.inc
 total += batch_bytes
 if (in_size - total) < batch_bytes
   batch_bytes = (in_size - total)
 end
 buffer = in_file.sysread(batch_bytes)
end
p_bar.finish
person DEfusion    schedule 19.03.2009
comment
хорошо сделано. И спасибо, что познакомили меня с жемчужиной индикатора прогресса. - person pisswillis; 19.03.2009
comment
полезный драгоценный камень +1 за это :) - person JstRoRR; 28.06.2014

Сверните свой собственный, используя IO.syswrite, IO.sysread.

Во-первых, определите длину индикатора выполнения (в символах). Затем этот псевдокод должен это сделать (НЕ ПРОВЕРЕНО):

infile = File.new("source", "r")
outfile = File.new("target", "w")

no_of_bytes = infile.length / PROGRESS_BAR_LENGTH

buffer = infile.sysread(no_of_bytes)
while buffer do
 outfile = syswrite(buffer)
 update_progress_bar()
 buffer = infile.sysread(no_of_bytes)
end

где update_progress_bar() — ваш метод увеличения индикатора выполнения на один символ. Вышеупомянутое не проверено и, вероятно, вызовет у пуриистов недомогание. В частности, EOFException может испортить цикл. Также вам понадобится какой-то способ убедиться, что все байты записаны, если no_of_bytes не является целым числом.

person pisswillis    schedule 19.03.2009
comment
Отличная отправная точка, но, поскольку я не мог ее редактировать, мне пришлось добавить свой собственный ответ с моим рабочим кодом. - person DEfusion; 19.03.2009

Или вы можете просто взломать его, чтобы использовать scp, если это индикатор выполнения, который вам нравится:

def copy(source, dest)
  `scp #{source} localhost:#{dest}`
end

Вы должны убедиться, что имена источника и назначения правильно экранированы для системного вызова. Тег localhost: заставляет scp копировать файлы так же, как между компьютерами, поэтому отображается индикатор выполнения.

person rampion    schedule 19.03.2009
comment
Какая отличная идея, не подумал об этом. - person DEfusion; 19.03.2009

В Windows не забудьте добавить «b» для двоичных файлов, поэтому «w» и «r» должны быть «wb» и «rb» для двоичных файлов.

in_file     = File.new(in_name, "rb")
out_file    = File.new(out_name, "wb")
person Halogen II    schedule 25.07.2014