Šajā rakstā tiks atklātas dažas nepārprotamas lietas, kas saistītas ar lietošanu aizstājējzīmes kopējot, neviennozīmīga komandu uzvedība cp kopējot, kā arī metodes, kas ļauj pareizi kopēt milzīgu skaitu failu, neizlaižot vai neavarējot.
Pieņemsim, ka mums ir jākopē viss no mapes /source uz mapi /target.
Pirmā lieta, kas nāk prātā, ir:
cp /source/* /target
Nekavējoties labosim šo komandu uz:
cp -a /source/* /target
Taustiņš -a pievienos visu atribūtu kopēšanu, tiesības un pievienos rekursiju. Ja precīza tiesību reproducēšana nav nepieciešama, pietiek ar atslēgu -r.
Pēc kopēšanas mēs atklāsim, ka ne visi faili tika kopēti - faili, kas sākas ar punktu, piemēram:
.profile
.local
.mc
un tamlīdzīgi.
Kāpēc tas notika?
Tā kā aizstājējzīmes apstrādā apvalks (bash tipiskā gadījumā). Pēc noklusējuma bash ignorēs visus failus, kas sākas ar punktiem, jo tos uzskata par slēptiem. Lai izvairītos no šādas uzvedības, mums būs jāmaina uzvedība bash izmantojot komandu:
shopt -s dotglob
Lai nodrošinātu, ka šīs uzvedības izmaiņas saglabājas arī pēc atsāknēšanas, mapē varat izveidot failu wildcard.sh ar šo komandu. /etc/profile.d (Iespējams, jūsu izplatīšanai ir cita mape).
Un, ja avota direktorijā nav failu, apvalks nevarēs neko aizstāt zvaigznītes vietā, un arī kopēšana neizdosies ar kļūdu. Pret šo situāciju ir varianti failglob и nullglob. Mums būs jāiestata failglob, kas novērsīs komandas izpildi. nullglob nedarbosies, jo tā pārvērš virkni ar aizstājējzīmēm, kas neatrada atbilstību, par tukšu virkni (nulles garums), kas cp radīs kļūdu.
Tomēr, ja mapē ir tūkstošiem failu vai vairāk, tad no aizstājējzīmju pieejas ir jāatsakās pavisam. Fakts ir tāds bash paplašina aizstājējzīmes ļoti garā komandrindā, piemēram:
cp -a /souce/a /source/b /source/c …… /target
Komandrindas garumam ir ierobežojums, ko mēs varam uzzināt, izmantojot komandu:
getconf ARG_MAX
Iegūsim maksimālo komandrindas garumu baitos:
2097152
Или:
xargs --show-limits
Mēs iegūstam kaut ko līdzīgu:
….
Maximum length of command we could actually use: 2089314
….
Tātad, iztiksim bez aizstājējzīmēm.
Vienkārši rakstīsim
cp -a /source /target
Un šeit mēs saskaramies ar uzvedības neskaidrību cp. Ja mape /target neeksistē, mēs iegūsim to, kas mums nepieciešams.
Tomēr, ja mērķa mape pastāv, faili tiks kopēti mapē /target/source.
Mēs ne vienmēr varam iepriekš izdzēst mapi /target, jo tajā var būt mums nepieciešamie faili, un mūsu mērķis, piemēram, ir papildināt /target failus ar failiem no /source.
Ja avota un mērķa mapēm tika nosaukti vienādi nosaukumi, piemēram, mēs kopējām no /source uz /home/source, tad mēs varētu izmantot komandu:
cp -a /source /home
Un pēc kopēšanas /home/source faili tiktu papildināti ar failiem no /source.
Tā ir loģiska problēma: mēs varam pievienot failus galamērķa direktorijā, ja mapēm ir vienādi nosaukumi, bet, ja tie atšķiras, tad avota mape tiks ievietota galamērķa iekšpusē. Kā kopēt failus no /source uz /target, izmantojot cp bez aizstājējzīmēm?
Lai apietu šo kaitīgo ierobežojumu, mēs izmantojam nepārprotamu risinājumu:
cp -a /source/. /target
Tie, kas pārzina DOS un Linux, jau visu ir sapratuši: katrā mapē ir 2 neredzamas mapes "." un “..”, kas ir pseidomapes saites uz pašreizējo un augstāko direktoriju.
Kopējot cp pārbauda esamību un mēģina izveidot /target/.
Šāds direktorijs pastāv, un tas ir /target
Faili no /source tiek pareizi kopēti mapē /target.
Tātad, pakariet to drosmīgā rāmī atmiņā vai pie sienas:
cp -a /source/. /target
Šīs komandas darbība ir skaidra. Viss darbosies bez kļūdām, neatkarīgi no tā, vai jums ir miljons failu vai nav neviena.
Atzinumi
Ja jums ir nepieciešams kopēt viss failus no vienas mapes uz citu, mēs neizmantojam aizstājējzīmes, labāk tos izmantot cp apvienojumā ar punktu avota mapes beigās. Tādējādi tiks kopēti visi faili, tostarp slēptie, un neizdosies neveikt miljoniem failu vai vispār neviena faila gadījumā.
Pēcvārds
vmspike ieteica komandas versiju ar līdzīgu rezultātu: