Alternatívy pre cp pre CLI
Známy web linuxlinks.com upozornil na program v Rust-e, ktorý nahrádza známy rm. Napadlo ma, či jeho autor neurobil aj verziu pre cp. A veru áno.
cp, cpz a iné
Program cp je najklasickejší a najzákladnejší program určený na kopírovanie súborov a adresárov, naprogramovaný v jazyku C. Je vskutku základný, nevie obnoviť prerušené kopírovanie, nekontroluje kontrolné súčty, nemá štatistiky priebehu ani odhad času (a to chýba najmä pri kopírovaní veľkých súborov), nemá synchronizáciu (teda vie len prepísať všetko, nevie porovnať zdroj a cieľ), vždy skopíruje celý obsah súborov.
Takže skutočný základ. A vo väčšine prípadov plne postačujúci.
Komu by to nepostačovalo, tak ten môže siahnuť po iných programoch. Ja zvyčajne používam rsync v aliase alias rcp rsync -hPur $*
(pozor, je to alias pre Emacs Eshell, ktorý sa definuje trošku odlišne). To mi pridá informácie o priebehu a tiež robí prírastkové kopírovanie.
Ale tých programov je viac, tak si ich len spomenieme. A spravíme si test, ako rýchlo dokážu pracovať.
Testovací adresár
V eshelle Emacsu som si spustil v adresári test_dir
jednoriadkový príkaz, ktorý mi vygeneroval 300 súborov s náhodou veľkosťou od 100 kB po 50 MB. Celková veľkosť obsahu adresára je 7488,48 MB, takže cca 7,4 GB.
Adresár som kopíroval na SSD disku, z jednej partície na druhú.
A ešte ten one-liner:
(dotimes (i 300) (let ((size (+ 100 (* (random 50000) 1024)))) (with-temp-buffer (insert (make-string size ?\0)) (write-file (format "file_%d" i)))))
A teraz konkrétne testy:
Pôvodným zámerom bolo spustiť takýto príkaz:for f in 1 2 3 4 5 { time cp -r test_dir /media/extended/$f }
Ale nefungovalo to ako som chcel, lebo to počítalo celkové kopírovanie počas piatich dieľčich (čo je z hľadiska zistenia priemeru jedného v poriadku, ale zaujímalo ma i to, či sa budú jednotlivé kopírovania líšiť, a veru sa aj!).
Ono v Eshell-i nie je time obyčajným externým programom, ale interne rozpoznávanou štruktúrou, ktorá sa aplikuje na celý nasledujúci job a keď je v { … }
bloku, tak sa zmeria práve vykonanie toho jedného a nie každá iterácia zvlášť.
Tak som to obišiel takto:
Príkaz kopírovania som spúšťal 5×, pomocou príkazu:bash -lc 'for f in {1..5}; do time cp -r test_dir /media/extended/$f; done'
(kde cp -r som nahrádzal vždy iným príkazom).
Fanúšikovia Emacsu mi hádam odpustia, že som ako úkrok bokom použil spustenie procesu bash-u. ☺
Počas kopírovania som nerobil s počítačom nič iné, bola nastavená fixná frekvencia CPU (všetky 4 jadrá na 1,6 GHz).
cp
S použitím cp -r
som dosiahol tieto výsledky:
kopírovanie č. | čas [s] |
---|---|
1 | 45,599 |
2 | 39,172 |
3 | 53,232 |
4 | 39,994 |
5 | 41,903 |
⌀ | 43,980 |
cpz
Na githube autora programu rmz som našiel tento program cpz (skratka od cp zippy). Je naprogramovaný v Rust-e a motiváciou autora bolo spraviť rýchlejšiu alternatívu v cp. Jeho použitie je identické ako v prípade cp.
S použitím cpz
som dosiahol tieto výsledky (cpz nepotrebuje parameter pre určenie rekurzívneho kopírovania):
kopírovanie č. | čas [s] |
---|---|
1 | 43,907 |
2 | 34,271 |
3 | 33,244 |
4 | 42,185 |
5 | 34,550 |
⌀ | 37,631 |
gcp
Z dokumentácie vyberáme:
gcp je kopírovací program na kopírovanie súborov, voľne inšpirovaný príkazom cp, ale s funkciami, ako sú:
- indikácia priebehu prenosu;
- priebežné kopírovanie v prípade problému: preskočí problematický súbor a pokračuje ďalej;
- zaznamenávanie stavu kopírovania: ktoré súbory boli skutočne skopírované;
- úprava názvov na zvládnutie obmedzení cieľového súborového systému (napr. odstránenie nekompatibilných znakov ako "?" alebo "*" na VFAT);
- vynútená serializácia kopírovania: nové súbory na kopírovanie sa pridávajú do globálneho frontu;
- správa zoznamu prenosov: gcp môže uložiť zoznam súborov na kopírovanie a neskôr ho znovu použiť;
- približná kompatibilita možností s cp (približná, pretože správanie nie je úplne rovnaké);
S použitím gcp -r
som dosiahol tieto výsledky:
kopírovanie č. | čas [s] |
---|---|
1 | 180,653 |
2 | 191,212 |
3 | 142,631 |
4 | 194,301 |
5 | 123,246 |
⌀ | 166,409 |
Samozrejme, nechal som zapnuté zobrazovanie priebehu, pretože je to hlavný dôvod použia.
Len dodám, že gcp je v štandardných repozitároch distribúcií.
Screenshot, aby čitateľ videl, ako vyzerá progress-bar pri kopírovaní:
rsync
Rsync je všeobecne známy nástroj na synchronizáciu a kopírovanie súborov medzi dvomi miestami, lokálne alebo naprieč sieťou (napr. cez ssh). Na rozdiel od cp, rsync dokáže efektívne prenášať iba zmenené časti súborov. Je na ňom postavených veľa utilít ako grsync, luckybackup či timeshift.
Hlavné výhody:
- incrementálna synchronizácia – teda len zmenené súbory;
- kompresia prenosu – s parametrom
-z
; - pokračovanie v prerušenom prenose;
- presná replikácia atribútov (práva, časy, vlastníctvo) – s parametrom
-a
; - možnosť vynechať alebo nanútiť konkrétne súbory/adresáre;
- zrkadlenie – parameter
--delete
zabezpečí, že súbory odstránené v zdrojovom adresári sa zmažú aj v cieľovom.
S použitím rsync -hPur
som dosiahol tieto výsledky:
kopírovanie č. | čas [s] |
---|---|
1 | 80,238 |
2 | 105,415 |
3 | 62,813 |
4 | 103,318 |
5 | 61,158 |
⌀ | 82,564 |
Opäť - nechal som zapnuté zobrazovanie priebehu, lebo to je tiež významná výhoda oproti cp.
tar
A ešte jedna exotika: použitie tar, ktorý vytvorí a potom rozbalí archív medzi dvomi adresármi.
Tu som ale ručne spúštal tento príkaz 5×:
tar cf - test_dir | tar xf - -C /media/extended/
kopírovanie č. | čas [s] |
---|---|
1 | 46,844 |
2 | 31,866 |
3 | 30,419 |
4 | 45,166 |
5 | 35,252 |
⌀ | 37,909 |
Záver
Časy pri kopírovaní sú ovplyvnené množstvom faktorov – často tak veľmi, že rovnaký príkaz pri viacerých spusteniach dáva rozdielne výsledky.
Dôvodom môže byť rozdielne zaťaženie hardvéru – aj keď som počítač počas testu nepoužíval, len sa na neho pozeral (žeby kvantový efekt pozorovateľa 😏?), ale zase nejaký iný proces v OS mohol dačo iné robiť. Potom je tu nejaká cache, na ktorou nemám (alebo o tom neviem) kontrolu. A možno aj iné veci…
Takže výsledky v jednej tabuľke (a org módom generovaným grafom 😏):
program | ⌀ čas [s] | ASCII graf |
---|---|---|
(menej je lepšie) | ||
cp | 43,980 | WWW |
cpz | 37,631 | WWl |
gcp | 166,409 | WWWWWWWWWWWh |
rsync | 82,564 | WWWWWV |
tar | 37,909 | WWl |
A aké je ponaučenie?
Grafické „parádičky“ sú výhodné, lebo má človek informáciu o priebehu. gcp, ktorého progress-bar je postavený na python knižnici, pokuľháva vo výkone, zvlášť v našom prípade, keď sa emuluje zobrazenie bash procesu do eshell terminálu. rsync je pomalší samozrejme aj preto, že musí každú položku pred kopírovaním overiť.
tar príjemne prekvapil, ale vzhľadom na syntax je použitie otázne, hoci by sa to dalo zaobaliť do funkcie. Oproti cp alebo rsync robí menej volaní jadra, vie použiť veľké bloky a sústredí sa čisto na sekvenčné čítanie/zápis, bez všetkého navyše, čo robí rsync, ktorý pri stovkách súborov asi má dopad na výkon.
cpz a Rust priniesli trochu rýchlosti, ale v našom prípade to bolo úplne irelevantné. Ale zase je to „hype“ jazyk, no…
Takže pre mňa je to jasné: 90% obslúžim pomocou cp, zvyšok, najmä veľké súbory alebo pri práci s pomalými diskami, pomocu rsync.
Pre pridávanie komentárov sa musíte prihlásiť.