Progress bar pre rsync (Tcl/Tk, Emacs,…)
Pri kopírovaní/synchronizovaní súborov a adresárov pomocou rsync máme dostupné informácie v konzole. Ako z nich spraviť „progress bar“ a ako ho použiť napr. v dired/pre Emacs?
Motivácia + slabina dired
Pôvodný zámer ísť na bicykel zhatilo počasie – veľkolepý lejak a následné blato. Pracovať sa mi už (a znovu) nechcelo, tak som sa rozhodol precvičiť sa v menej používanom jazyku Tcl (s Tk) a Elisp. Nakoniec to bolo také rýchle a stručné, že precvičovať nebolo veľmi čo 😀.
Užívatelia GNU Emacsu používajúci súborový manažér dired, alebo jeho deriváty ako diredc či Sunrise Commander často narazia na nepríjemnú vec ak kopírujú veľké súbory najmä na pomalé média, ako je USB kľúč. Vstavaná funkcia pre kopírovanie dired-do-copy
si uzurupje čas pre seba a Emacs je v tomto momente nerenspozívny. Funkcia dired-async-do-copy
dokáže pracovať na pozadí, ale zase jeden nemá poriadny prehľad, koľko sa toho skopírovalo.
Preto na kopírovanie v týchto prípadoch používam rsync. Ten je vhodný samozrejme i v bash-i, lebo ani tam klasický cp neposkytuje dostatočné informácie (preto je šikovný i program gcp).
Interaktívnu funkciu pre rsync mám v Emacse roky, ktorá v druhom buffri zobrazuje jeho postup, ale teraz som sa rozhodol pridať i tzv. progress bar, t.j. grafické znázornenie priebehu. Najprv som to chcel spraviť cez (inak) šikovný YAD, ale tam už bežiaci program nevie prijať informácie o takomto vstupe. Resp. nepodarilo sa mi to nájsť a ani AI nemala žiaden fungujúci návod. Zato sebavedomých nezmyslov niekoľko 🙄.
Tak som sa rozhodol pre použitie grafického frameworku Tk pre mocný skriptovací jazyk Tcl.
Výsledok je taký:
![]() |
Obr. 0: „Progress bar“ v akcii |
Ako takútu „nádheru“ dosiahnuť?
Možno nemotorne, ale prostredníctvom troch skriptov.
Princípom je počítanie, koľko súborov musí rsync prekopírovať alebo zosynchronizovať a potom pri tejto činnosti počítať percento priebehu a to zobrazovať.
Samotné skripty sú na mojom gitlabe.
copy-scipt.sh
Tento bash skript zistí počet súborov a následne ich začne kopírovať. Áno, áno, nevie, aká bude celková veľkosť prenesených dát. Túto informáciu rsync neposkytuje. Takže 50% v progress bar-e znamená, že bola prekopírovaná polovica súborov. Ale myslím, že pre bežné použitie je to dobrá informácia a tiež aj informácia o tom, „že niečo sa deje“.
rsync-progress.sh
Toto je hlavný skript, ktorý interaguje s užívateľom. Takže namiesto klasického:
cp <súbor, adresár, alebo viac súborov či adresárov> <destinácia>
použijeme
rsync-progress.sh <súbor, adresár, alebo viac súborov či adresárov> <destinácia>
Alebo si na to niekto môže spraviť alias apod.
Pred prvým použitím je ale potrebné editovať riadok č. 3, v ktorom je definované, kde sa pomocné skripty nachádzajú, napríklad:
path_to_scripts="/home/richard/bin/tcl-rsync-progressbar/"
(pozor na konci musí byť /
).
A teda tento program nielenže začne kopírovanie, ale do Tcl/Tk programu tcl-progressbar.sh posiela informácie o priebehu.
tcl-progressbar.tcl
Tento program číta štandardný vstup, na ktorom je číslo, percento z programu rsync-progress.sh, a to zobrazuje. Nič viac.
V programe možno ešte nastaviť veľkosť progress bar-u a prípadne umiestnenie okna, ak sa nám nepáči, kde nám to ukladá náš okenný manažér.
ešte funkcia do Emacsu
Táto funkcia:
(defun sr-rsync-copy-with-progressbar (dest) "Copy files using rsync with Tcl/Tk progressbar." (interactive (list (expand-file-name (read-file-name "rsync to: " (dired-dwim-target-directory))))) (let ((files (dired-get-marked-files nil current-prefix-arg)) (command "/home/richard/bin/tcl-rsync-progressbar/rsync-progress.sh ")) (dolist (file files) (setq command (concat command (shell-quote-argument file) " "))) (setq command (concat command (shell-quote-argument dest))) (async-shell-command command "*rsync*") (dired-unmark-all-marks) (other-window 1) (sleep-for 1) (dired-revert) (revert-buffer nil t nil)) (message "* rsync done *") (let ((buffer-name "*rsync*")) (if (get-buffer buffer-name) (when (yes-or-no-p (format "Do you want to close the buffer %s? " buffer-name)) (kill-buffer buffer-name)) (message "Buffer %s does not exist." buffer-name))))
nám zjednoduší používanie v Emacse. Kopíruje takto označené súbory a adresáre v dired a jeho derivátoch, pričom nám ponúka i destináciu. Ako veľmi interaktívne, to závisí od použitého „completition“ frameworku toho-ktorého užívateľa (napr. fido, helm…).
Na nasledujúcich obrázkoch (lebo tých je tu zatiaľ málo) označím adresár i súbor a zavolám funkciu sr-rsync-copy-with-progressbar (hehe, to uvodzujúce „sr“ je tam preto, lebo som kedysi používal Sunrise Commander a takto som si označoval funkcie pre neho, hoci ho už teraz nepoužívam 😀).
Okno s progress bar-om nie je modálne, takže ho človek môže presunúť inam, na inú plochu a pod.
![]() |
![]() |
![]() |
Obr. 1 – 3: Kopírovanie v diredc |
![]() |
Obr. 4: Kopírovanie z príkaz. riadku v konzole |
Zrada rsync-u a slabé stránky programu
Pri spúštaní programu rsync-progress.sh a rsync z príkazového riadku vo všeobecnosti je potrebné dávať pozor na /
v cestách.
Len na ilustráciu:
rsync foo/bar destination
prekopírujefoo/bar
adresár tak, že tento adresárbar
i vytvorí v priečinkudestination
.
Ale
rsync foo/bar/ destination
spôsobí, že sa prekopíruje všetko „za“ onýmbar
, teda obsahbar
, ale nevytvorí sa samotný priečinokbar
v adresáridestination
.
Slabou stránkou programu ešte je, že načítava v programe rsync-progress.sh všetky argumenty okrem posledného ako zdrojové súbory/adresáre, a posledný argument je destinácia. Ak majú zdrojové súbory v názve medzery, chudák program si myslí, že to je už iný súbor/adresár a blbne. Takže zatiaľ nás stroje ešte neovládli! 😀
Navrhované riešenia ako --itemize-changes
a pod. neviedli k úspechu. No ale aspoň mám nejakú úlohu do budúcnosti.
Alebo niekto príde s vylepšením.
Záver
Ako spieva Frank Sinatra v „My Way“: „I did it my way“. A just a to je perfektné! Či nie?
Pre pridávanie komentárov sa musíte prihlásiť.
pekna praca.
Len ked ja nemam rad emacs a vim :D
Na bike sa chystam. budem off webu asi 3 tyzdne caka ma dlllhaaaa cesta. v pondelok som dal 160km za 8,5h.
A skadiaľ budeš mať trasu? Nech ti zakývame a podáme vodu :-)
kusok len :-)
denne cca 150km ale mozno aj viac.
rozmyslal som ako to je spravene, zaujimave riesenie s tym dry-run... asi moze existovat pripad, ze sa to bude lisit oproti skutocnosti