
În acest articol vor fi dezvăluite câteva aspecte mai puțin evidente legate de utilizarea la copiere, comportamente ambigue ale comenzii cp la copiere, precum și metode care permit copierea corectă a unui număr mare de fișiere fără omisiuni și erori.
Să presupunem că trebuie să copiem tot din folderul /source în folderul /target.
Primul lucru care îmi vine în minte este:
cp /source/* /targetSă corectăm imediat această comandă la:
cp -a /source/* /target Cheia -a va adăuga copierea tuturor atributelor, permisiunilor și va activa recursivitatea. Când nu este necesară reproducerea exactă a permisiunilor, este suficientă opțiunea -r.
După copiere, vom descoperi că nu toate fișierele au fost copiate — au fost ignorate fișierele care încep cu un punct, cum ar fi:
.profil
.local
.mc
și alte similare.
De ce s-a întâmplat asta?
Pentru că wildcards sunt procesate de shell (bash în cazul tipic). În mod implicit, bash ignoră toate fișierele care încep cu puncte, considerându-le ascunse. Pentru a evita acest comportament, va trebui să modificăm comportamentul bash folosind comanda:
shopt -s dotglob Pentru a păstra această modificare a comportamentului după repornire, puteți crea un fișier wildcard.sh cu această comandă în folderul /etc/profile.d (este posibil ca în distribuția dumneavoastră să fie într-un alt folder).
Și dacă în directorul sursă nu există fișiere, atunci shell-ul nu va putea înlocui nimic în locul asteriscului, iar copierea va eșua cu o eroare. Pentru o astfel de situație, există opțiuni failglob și nullglob. Va fi necesar să setăm failglob, care nu va permite execuția comenzii. nullglob nu va funcționa, deoarece aceasta transformă o linie cu wildcards fără potriviri într-o linie goală (de lungime zero), ceea ce cp va provoca o eroare.
Cu toate acestea, dacă în folder sunt mii de fișiere și mai mult, ar trebui să renunțăm complet la abordarea cu wildcards. Motivul este că bash dezvoltă wildcards într-o linie de comandă foarte lungă, de tipul:
cp -a /souce/a /source/b /source/c …… /targetExistă o limită asupra lungimii liniei de comandă, pe care o putem descoperi folosind comanda:
getconf ARG_MAXVom obține lungimea maximă a liniei de comandă în octeți:
2097152Sau:
xargs --show-limitsVom obține ceva de genul:
….
Lungimea maximă a comenzii pe care am putea-o folosi efectiv: 2089314
….Așadar, să ne descurcăm complet fără wildcards.
Să scriem pur și simplu
cp -a /source /target Și aici ne vom confrunta cu ambiguitatea comportamentului cp. Dacă folderul /target nu există, vom obține ceea ce ne trebuie.
Însă, dacă folderul target există, fișierele vor fi copiate în folderul /target/source.
Nu întotdeauna putem șterge în prealabil folderul /target, deoarece acesta ar putea conține fișiere necesare și scopul nostru, de exemplu, este să completăm fișierele din /target cu cele din /source.
Dacă folderele sursă și destinație s-ar numi la fel, de exemplu, dacă am copia din /source în /home/source, am putea folosi comanda:
cp -a /source /homeȘi după copiere, fișierele din /home/source ar fi completate cu fișiere din /source.
O astfel de problemă logică: putem completa fișierele din directorul destinație, dacă folderele se numesc la fel, însă, dacă sunt diferite, atunci folderul sursă va fi plasat în interiorul destinației. Cum putem copia fișiere din /source în /target folosind cp fără caractere wildcard?
Pentru a ocoli această restricție neplăcută, folosim o soluție neobișnuită:
cp -a /source/. /targetCei care sunt bine familiarizați cu DOS și Linux au înțeles deja totul: în fiecare folder există 2 foldere invizibile „.” și „..”, care sunt linkuri pseudofolder pentru directorul curent și cel superior.
- La copiere,
cpse verifică existența și se încearcă să se creeze /target/. - Un astfel de director există și este /target.
- Fișierele din /source au fost copiate corect în /target.
Așadar, să reținem bine:
cp -a /source/. /target
Comportamentul acestei comenzi este clar. Totul va funcționa fără erori, indiferent dacă aveți un milion de fișiere sau niciunul.
Conclusions
Dacă trebuie să copiati tot fișiere dintr-un folder în altul, evitați utilizarea caracterelor wildcard, în locul lor este mai bine să folosiți cp în combinație cu punctul de la sfârșitul folderului sursă. Aceasta va copia toate fișierele, inclusiv cele ascunse și nu se va prăbuși în fața unui milion de fișiere sau în absența totală a acestora.
Cuvânt înainte
a propus o variantă asemănătoare pe care produce rezultate identice:
cp -a -T /source /target
cp -aT /source /target ATENȚIE: litera mare T contează. Dacă te încurci, vei obține o harababură totală: direcția copiilor se va schimba.
Mulțumiri:
- Companiei pentru sprijin și posibilitatea publicării pe blogul său din Habr.
- Pentru imaginea . Imaginea este foarte mare și detaliată, poate fi deschisă într-o fereastră separată.
P.S. Errorele observate pot fi raportate în privat. Îmi cresc karma pentru asta.
Sursa: habr.com
