cp komanda: ispravno kopirajte foldere datoteka u *nix
Ovaj članak će otkriti neke neočigledne stvari vezane za korištenje zamjenski znakovi kod kopiranja, dvosmisleno ponašanje komande cp prilikom kopiranja, kao i metode koje vam omogućavaju da ispravno kopirate ogroman broj datoteka bez preskakanja ili pada.
Recimo da moramo kopirati sve iz /source foldera u /target folder.
Prva stvar koja pada na pamet je:
cp /source/* /target
Ispravimo odmah ovu naredbu na:
cp -a /source/* /target
Ključ -a će dodati kopiranje svih atributa, prava i dodati rekurziju. Kada nije potrebna tačna reprodukcija prava, dovoljan je ključ -r.
Nakon kopiranja, otkrit ćemo da nisu svi fajlovi kopirani - fajlovi koji počinju tačkom kao što je:
.profile
.local
.mc
i slično.
Zašto se to dogodilo?
Zato što džoker obrađuje ljuska (bash u tipičnom slučaju). Podrazumevano, bash će ignorisati sve datoteke koje počinju tačkama, jer ih tretira kao skrivene. Da bismo izbjegli ovakvo ponašanje, morat ćemo promijeniti ponašanje bash koristeći naredbu:
shopt -s dotglob
Da biste osigurali da se ova promjena ponašanja nastavi nakon ponovnog pokretanja, možete kreirati wildcard.sh datoteku s ovom naredbom u mapi /etc/profile.d (Možda vaša distribucija ima drugu fasciklu).
A ako u izvornom direktoriju nema datoteka, ljuska neće moći ništa zamijeniti umjesto zvjezdice, a kopiranje također neće uspjeti s greškom. Postoje opcije protiv ove situacije failglob и nullglob. Moraćemo da postavimo failglob, što će spriječiti izvršenje naredbe. nullglob neće raditi, jer pretvara niz sa zamjenskim znakovima koji nisu pronašli podudaranje u prazan niz (nulte dužine), koji za cp će uzrokovati grešku.
Međutim, ako postoje hiljade datoteka ili više u folderu, onda bi pristup sa zamjenskim znakovima trebao biti potpuno napušten. Činjenica je da bash proširuje zamjenske znakove u veoma dugu komandnu liniju kao što je:
cp -a /souce/a /source/b /source/c …… /target
Postoji ograničenje dužine komandne linije, što možemo saznati pomoću naredbe:
getconf ARG_MAX
Hajde da dobijemo maksimalnu dužinu komandne linije u bajtovima:
2097152
Ili:
xargs --show-limits
Dobijamo nešto poput:
….
Maximum length of command we could actually use: 2089314
….
Dakle, hajdemo bez zamjenskih znakova.
Hajde da napišemo
cp -a /source /target
I tu smo suočeni sa dvosmislenošću ponašanja cp. Ako /target folder ne postoji, onda ćemo dobiti ono što nam je potrebno.
Međutim, ako ciljni folder postoji, tada će datoteke biti kopirane u /target/source folder.
Ne možemo uvijek unaprijed izbrisati mapu /target, jer može sadržavati datoteke koje su nam potrebne i naš cilj je, na primjer, da dopunimo datoteke u /target datotekama iz /source.
Ako su izvorni i odredišni folderi nazvani istim imenom, na primjer, kopirali smo iz /source u /home/source, onda bismo mogli koristiti naredbu:
cp -a /source /home
I nakon kopiranja, fajlovi u /home/source bi bili dopunjeni fajlovima iz /source.
Ovo je logičan problem: možemo dodati datoteke u odredišni direktorij ako su mape nazvane istim imenom, ali ako se razlikuju, onda će izvorna mapa biti smještena unutar odredišta. Kako kopirati datoteke iz /source u /target koristeći cp bez zamjenskih znakova?
Da bismo zaobišli ovo štetno ograničenje, koristimo neočigledno rješenje:
cp -a /source/. /target
Oni koji su upoznati sa DOS-om i Linuxom već su sve shvatili: unutar svake fascikle nalaze se 2 nevidljiva foldera “.” i “..”, koji su veze pseudo-foldera sa trenutnim i višim direktorijumima.
Prilikom kopiranja cp provjerava postojanje i pokušava kreirati /target/.
Takav direktorij postoji i to je /target
Fajlovi iz /source su ispravno kopirani u /target.
Dakle, objesite ga u podebljani okvir u svom sjećanju ili na zid:
cp -a /source/. /target
Ponašanje ove naredbe je jasno. Sve će raditi bez grešaka, bez obzira da li imate milion fajlova ili nijedan.
nalazi
Ako trebate kopirati sve datoteke iz jednog foldera u drugi, ne koristimo zamjenske znakove, bolje ih je koristiti cp u kombinaciji s tačkom na kraju izvorne mape. Ovo će kopirati sve datoteke, uključujući i skrivene, i neće uspjeti s milionima datoteka ili bez ikakvih datoteka.
Posle reči
vmspike predložio verziju komande sa sličnim rezultatom: