Comanda cp: copiați folderele fișierelor corect în *nix

Comanda cp: copiați folderele fișierelor corect în *nix

Acest articol va dezvălui câteva lucruri neevidente legate de utilizarea metacaractere la copiere, comportament ambiguu al comenzii cp la copiere, precum și metode care vă permit să copiați corect un număr mare de fișiere fără săriți sau să vă blocați.

Să presupunem că trebuie să copiem totul 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

Ключ -a va adăuga copierea tuturor atributelor, drepturile și va adăuga recursivitate. Atunci când reproducerea exactă a drepturilor nu este necesară, este suficientă o cheie -r.

După copiere, vom descoperi că nu toate fișierele au fost copiate - fișiere care încep cu un punct precum:

.profile
.local
.mc

și altele asemenea.

De ce s-a întâmplat asta?

Deoarece metacaracterele sunt procesate de către shell (bash într-un caz tipic). În mod implicit, bash va ignora toate fișierele care încep cu puncte, deoarece le tratează ca ascunse. Pentru a evita acest comportament va trebui să schimbăm comportamentul bash folosind comanda:

shopt -s dotglob

Pentru a vă asigura că această modificare a comportamentului persistă după o repornire, puteți crea un fișier wildcard.sh cu această comandă în dosar /etc/profile.d (Poate că distribuția dvs. are un folder diferit).

Și dacă nu există fișiere în directorul sursă, atunci shell-ul nu va putea înlocui nimic în locul asteriscului, iar copierea va eșua, de asemenea, cu o eroare. Există opțiuni împotriva acestei situații failglob и nullglob. Va trebui să setăm failglob, care va împiedica executarea comenzii. nullglob nu va funcționa, deoarece convertește un șir cu caractere metalice care nu a găsit o potrivire într-un șir gol (lungime zero), care pentru cp va provoca o eroare.

Cu toate acestea, dacă există mii de fișiere sau mai multe în dosar, atunci abordarea wildcards ar trebui abandonată cu totul. Adevărul este că bash extinde metacaracterele într-o linie de comandă foarte lungă, cum ar fi:

cp -a /souce/a /source/b /source/c …… /target

Există o limită a lungimii liniei de comandă, pe care o putem afla folosind comanda:

getconf ARG_MAX

Să obținem lungimea maximă a liniei de comandă în octeți:

2097152

sau:

xargs --show-limits

Primim ceva de genul:

….
Maximum length of command we could actually use: 2089314
….

Așadar, să renunțăm cu totul la wildcards.

Să scriem doar

cp -a /source /target

Și aici ne confruntăm cu ambiguitatea comportamentului cp. Dacă folderul /target nu există, atunci vom obține ceea ce avem nevoie.

Totuși, dacă folderul țintă există, atunci fișierele vor fi copiate în folderul /target/source.

Nu putem șterge întotdeauna folderul /target în avans, deoarece acesta poate conține fișiere de care avem nevoie și scopul nostru, de exemplu, este de a completa fișierele din /target cu fișiere din /source.

Dacă folderele sursă și destinație au fost numite același, de exemplu, am copiat din /sursă în /home/source, atunci am putea folosi comanda:

cp -a /source /home

Și după copiere, fișierele din /home/source ar fi suplimentate cu fișiere din /source.

Aceasta este o problemă logică: putem adăuga fișiere în directorul de destinație dacă folderele sunt denumite la fel, dar dacă sunt diferite, atunci folderul sursă va fi plasat în interiorul destinației. Cum să copiați fișierele din /sursă în /țintă folosind cp fără caractere joker?

Pentru a ocoli această limitare dăunătoare, folosim o soluție neevidentă:

cp -a /source/. /target

Cei care sunt familiarizați cu DOS și Linux au înțeles deja totul: în fiecare folder există 2 foldere invizibile „.” și „..”, care sunt link-uri pseudo-foldere către directoarele curente și superioare.

  • La copiere cp verifică existența și încearcă să creeze /target/.
  • Un astfel de director există și este /target
  • Fișierele din /source sunt copiate corect în /target.

Așadar, atârnă-l într-un cadru îndrăzneț în memorie sau pe perete:

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 deloc.

Constatări

Dacă trebuie să copiați toate fișiere dintr-un folder în altul, nu folosim wildcard-uri, este mai bine să le folosim în schimb cp combinat cu un punct la sfârșitul folderului sursă. Acest lucru va copia toate fișierele, inclusiv cele ascunse, și nu va eșua cu milioane de fișiere sau cu niciun fișier.

postfață

vmspike a sugerat o versiune de comandă cu un rezultat similar:

cp -a -T /source /target

Oz_Alex

cp -aT /source /target

NOTĂ: majuscule T are sensul. Dacă îl amestecați, veți obține un gunoi complet: direcția de copiere se va schimba.
Multumesc:

  • companie RUVDS.COM pentru sprijin și oportunitatea de a publica pe blogul tău pe Habré.
  • Pe imagine Concept triplu. Poza este foarte mare și detaliată, poate fi deschisă într-o fereastră separată.

PS Vă rugăm să trimiteți orice erori pe care le observați într-un mesaj privat. Îmi măresc karma pentru asta.

Comanda cp: copiați folderele fișierelor corect în *nix

Sursa: www.habr.com

Adauga un comentariu