Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby show progress when copying files

I'd like to be able to show the progress of a file copy operation when copying files using Ruby (currently using FileUtils.cp) I've tried setting the verbose option to true but that just seems to show me the copy command issued.

I'm running this script from command line at the moment so ideally I'd like to be able to present something like SCP does when it copies files, but I'm not too fussed about the presentation as long as I can see the progress.

like image 547
DEfusion Avatar asked Mar 19 '09 11:03

DEfusion


2 Answers

As I don't have enough rep to edit answers yet here is my version based on pisswillis answer, I found a progress bar gem which I'm also using in my example. I have tested this and it has worked OK so far, but it could do with some cleaning up:

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
like image 117
DEfusion Avatar answered Sep 18 '22 23:09

DEfusion


Roll your own using IO.syswrite, IO.sysread.

First, decide length of progress bar (in chars).. then this pseudo code should do it (NOT TESTED):

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

where update_progress_bar() is your method to increment the progress bar by one char. The above is not tested and will probably make ruby purists ill. In particular an EOFException might mess up the loop. Also you will need some way of making sure that all the bytes are written if no_of_bytes is not an integer.

like image 23
pisswillis Avatar answered Sep 18 '22 23:09

pisswillis