cp komanda: teisingai nukopijuokite failų aplankus į *nix
Šiame straipsnyje bus atskleista keletas neakivaizdžių dalykų, susijusių su naudojimu pakaitos simboliai kopijuojant, dviprasmiškas komandų elgesys cp kopijuojant, taip pat metodai, leidžiantys teisingai nukopijuoti daugybę failų nepraleidžiant ar nesudūžtant.
Tarkime, kad turime nukopijuoti viską iš aplanko /source į aplanką /target.
Pirmas dalykas, kuris ateina į galvą, yra:
cp /source/* /target
Iš karto pataisykime šią komandą į:
cp -a /source/* /target
Raktas -a pridės visų atributų, teisių kopijavimą ir pridės rekursiją. Kai nereikia tiksliai atkurti teisių, pakanka rakto -r.
Nukopijavę pamatysime, kad ne visi failai buvo nukopijuoti – failai prasideda tašku, pavyzdžiui:
.profile
.local
.mc
ir panašiai.
Kodėl taip atsitiko?
Kadangi pakaitos simbolius apdoroja apvalkalas (bash tipiniu atveju). Pagal numatytuosius nustatymus bash nepaisys visų failų, prasidedančių taškais, nes laiko juos paslėptais. Norėdami išvengti tokio elgesio, turėsime pakeisti elgesį bash naudojant komandą:
shopt -s dotglob
Norėdami užtikrinti, kad šis elgsenos pokytis išliktų po perkrovimo, galite sukurti failą wildcard.sh su šia komanda aplanke /etc/profile.d (Galbūt jūsų platinimas turi kitą aplanką).
Ir jei šaltinio kataloge nėra failų, apvalkalas negalės niekuo pakeisti žvaigždutės, o kopijavimas taip pat nepavyks dėl klaidos. Yra alternatyvų prieš šią situaciją failglob и nullglob. Mums reikės nustatyti failglob, kuris neleis vykdyti komandos. nullglob neveiks, nes eilutę su pakaitos simboliais, kurios nerado atitikties, konvertuoja į tuščią eilutę (nulio ilgio), kuri cp sukels klaidą.
Tačiau jei aplanke yra tūkstančiai ar daugiau failų, pakaitos simbolių metodo reikėtų visiškai atsisakyti. Faktas yra tas bash išplečia pakaitos simbolius į labai ilgą komandinę eilutę, pvz.:
cp -a /souce/a /source/b /source/c …… /target
Komandų eilutės ilgis yra ribojamas, kurį galime sužinoti naudodami komandą:
getconf ARG_MAX
Gaukime maksimalų komandų eilutės ilgį baitais:
2097152
Или:
xargs --show-limits
Gauname kažką panašaus:
….
Maximum length of command we could actually use: 2089314
….
Taigi, apsieikime be pakaitos simbolių.
Tiesiog rašykime
cp -a /source /target
Ir čia susiduriame su elgesio dviprasmiškumu cp. Jei aplanko /target nėra, mes gausime tai, ko mums reikia.
Tačiau jei tikslinis aplankas yra, failai bus nukopijuoti į /target/source aplanką.
Ne visada galime iš anksto ištrinti aplanką /target, nes jame gali būti failų, kurių mums reikia, o mūsų tikslas, pavyzdžiui, yra papildyti /target esančius failus iš /source.
Jei šaltinio ir paskirties aplankai būtų pavadinti vienodai, pavyzdžiui, kopijuodavome iš /source į /home/source, tada galėtume naudoti komandą:
cp -a /source /home
O nukopijavus /home/source esantys failai būtų papildyti failais iš /source.
Tai logiška problema: galime pridėti failus į paskirties katalogą, jei aplankai pavadinti vienodai, tačiau jei jie skiriasi, šaltinio aplankas bus patalpintas paskirties aplanke. Kaip kopijuoti failus iš /source į /target naudojant cp be pakaitos simbolių?
Norėdami apeiti šį žalingą apribojimą, naudojame neakivaizdų sprendimą:
cp -a /source/. /target
Tie, kurie yra susipažinę su DOS ir Linux, jau viską suprato: kiekviename aplanke yra 2 nematomi aplankai „. ir „..“, kurie yra pseudoaplankų nuorodos į dabartinį ir aukštesnius katalogus.
Kopijuojant cp tikrina, ar nėra, ir bando sukurti /target/.
Toks katalogas egzistuoja ir yra /target
Failai iš /source teisingai nukopijuoti į /target.
Taigi, pakabinkite jį į paryškintą rėmelį atmintyje arba ant sienos:
cp -a /source/. /target
Šios komandos elgesys yra aiškus. Viskas veiks be klaidų, nepaisant to, ar turite milijoną failų, ar jų visai nėra.
išvados
Jei reikia kopijuoti visi failus iš vieno aplanko į kitą, nenaudojame pakaitos simbolių, geriau juos naudoti cp kartu su tašku šaltinio aplanko pabaigoje. Taip bus nukopijuoti visi failai, įskaitant paslėptus, ir nepavyks, kai bus milijonai failų arba jų visai nebus.
Afterword
vmspike pasiūlė komandos versiją su panašiu rezultatu: