Ruby mostrar o progresso ao copiar arquivos
Pergunta
Eu gostaria de ser capaz de mostrar o progresso de uma operação de cópia de arquivo ao copiar arquivos usando Ruby (usando atualmente FileUtils.cp) Eu tentei definindo a opção verbose
para true
mas que apenas parece-me mostrar a cópia comando emitido.
Estou executando esse script de linha de comando no momento, então Idealmente, eu gostaria de ser capaz de apresentar algo como SCP faz arquivos quando se copia, mas eu não estou com muita pressa sobre a apresentação, enquanto eu puder ver o progresso.
Solução
Como eu não tenho rep suficiente para editar respostas ainda aqui é a minha versão com base na resposta pisswillis, eu encontrei um barra de progresso gem que eu também estou usando no meu exemplo. Eu testei isso e tem funcionado bem até agora, mas poderia fazer com alguma limpeza:
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
Outras dicas
Roll seu próprio utilizando IO.syswrite, IO.sysread.
Em primeiro lugar, a duração da barra de progresso (em caracteres) decidir .. então este código pseudo deve fazê-lo (não testado):
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
onde update_progress_bar () é o seu método para incrementar a barra de progresso por um caractere. O acima não é testado e provavelmente fará com que os puristas rubi doente. Em particular um EOFException poder atrapalhar o loop. Além disso, você vai precisar de alguma maneira de ter certeza que todos os bytes são escritos se no_of_bytes não é um inteiro.
Ou você poderia apenas cortá-lo de usar scp, se essa é a barra de progresso que você gosta:
def copy(source, dest)
`scp #{source} localhost:#{dest}`
end
Você tem que ter certeza a origem e os nomes dest estão devidamente escapou para uma chamada de sistema. O localhost:
tag marcas scp copiar os arquivos como faz entre computadores, então ele irá mostrar uma barra de progresso.
No Windows não se esqueça de adicionar o 'b' para arquivos binários, de modo 'w' e 'r' deve ser 'wb' e 'rb' para arquivos binários.
in_file = File.new(in_name, "rb")
out_file = File.new(out_name, "wb")