2009-03-19 6 views
8

Chciałbym móc pokazać postęp operacji kopiowania plików podczas kopiowania plików za pomocą Ruby (obecnie przy użyciu FileUtils.cp) Próbowałem ustawić opcję verbose na true, ale to po prostu wydaje mi się pokazywać wydane polecenie kopiowania.Ruby pokaż postępy podczas kopiowania plików

Uruchomiłem ten skrypt z wiersza poleceń, więc najlepiej byłoby móc zaprezentować coś takiego jak SCP, gdy kopiuje pliki, ale nie jestem zbyt poruszony prezentacją tak długo jak ja widzę postęp.

Odpowiedz

14

Ponieważ nie mam wystarczającej liczby przedstawicieli do edycji odpowiedzi, tutaj jest moja wersja oparta na odpowiedzi pisswillis, znalazłem progress bar gem, którego używam również w moim przykładzie. Ja testowałem to i to działało OK do tej pory, ale może to zrobić niektóre oczyszczania:

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 
+2

ładnie wykonane. I dziękuję za wprowadzenie mnie do gem gem. – pisswillis

+0

przydatny klejnot +1 do tego :) – JstRoRR

7

Rzuć własne za pomocą IO.syswrite, IO.sysread.

pierwsze, decyduje długość paska postępu (w znakach) .. to ten pseudo kod powinien to zrobić (nie testowane):

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 

gdzie update_progress_bar() to metoda, aby podwyższyć o jeden pasek postępu zwęglać. Powyższe nie jest testowane i prawdopodobnie spowoduje, że purystom z rubinów będzie źle. W szczególności EOFException może zepsuć pętlę. Będziesz również potrzebował jakiegoś sposobu upewnienia się, że wszystkie bajty są zapisane, jeśli no_of_bytes nie jest liczbą całkowitą.

+0

Świetny punkt wyjścia, ale ponieważ nie mogłem go edytować, musiałem dodać własną odpowiedź z moim działającym kodem. – DEfusion

5

Albo może po prostu włamać się to do korzystania z SCP, jeśli to pasek postępu lubisz:

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

Musisz upewnić się, że źródło i przeznaczenie nazwy są właściwie uciekli do wywołania systemowego. Znacznik localhost: powoduje, że scp kopiuje pliki tak, jak robi to między komputerami, więc pokaże pasek postępu.

+0

Co za świetny pomysł, nie pomyślałem o tym. – DEfusion

0

Pod Windows nie zapomnij dodać „b” dla plików binarnych, tak „w” i ' r "powinno być" wb "i" rb "dla plików binarnych.

in_file  = File.new(in_name, "rb") 
out_file = File.new(out_name, "wb")