Echipa cp: copiere corectă a folderelor cu fișiere în *nix

Echipa cp: copiere corectă a folderelor cu fișiere în *nix

În acest articol vor fi dezvăluite câteva aspecte mai puțin evidente legate de utilizarea wildcards 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/* /target

Să 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 …… /target

Există o limită asupra lungimii liniei de comandă, pe care o putem descoperi folosind comanda:

getconf ARG_MAX

Vom obține lungimea maximă a liniei de comandă în octeți:

2097152

Sau:

xargs --show-limits

Vom 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/. /target

Cei 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, cp se 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

vmspike a propus o variantă asemănătoare pe care produce rezultate identice:

cp -a -T /source /target

Oz_Alex

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 RUVDS.COM pentru sprijin și posibilitatea publicării pe blogul său din Habr.
  • Pentru imaginea TripletConcept. 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.

Echipa cp: copiere corectă a folderelor cu fișiere în *nix

Sursa: habr.com

Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS 🔥 Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS | ProHoster