cp-opdracht: bestandsmappen correct kopiëren in *nix

cp-opdracht: bestandsmappen correct kopiëren in *nix

Dit artikel zal enkele niet voor de hand liggende zaken onthullen die verband houden met het gebruik van wildcards bij het kopiëren, dubbelzinnig opdrachtgedrag cp bij het kopiëren, evenals methoden waarmee u een groot aantal bestanden correct kunt kopiëren zonder over te slaan of te crashen.

Laten we zeggen dat we alles van de map /source naar de map /target moeten kopiëren.

Het eerste dat in je opkomt is:

cp /source/* /target

Laten we deze opdracht onmiddellijk corrigeren om:

cp -a /source/* /target

sleutel -a voegt het kopiëren van alle attributen en rechten toe en voegt recursie toe. Wanneer exacte reproductie van rechten niet vereist is, is een sleutel voldoende -r.

Na het kopiëren zullen we ontdekken dat niet alle bestanden zijn gekopieerd - bestanden die beginnen met een punt zoals:

.profile
.local
.mc

en dergelijke.

Waarom is dit gebeurd?

Omdat jokertekens worden verwerkt door de shell (bash in een typisch geval). Standaard negeert bash alle bestanden die met punten beginnen, omdat deze als verborgen worden behandeld. Om dit gedrag te voorkomen zullen we gedrag moeten veranderen bash met behulp van de opdracht:

shopt -s dotglob

Om ervoor te zorgen dat deze gedragsverandering na een herstart blijft bestaan, kunt u met deze opdracht een wildcard.sh-bestand in de map maken /etc/profile.d (Misschien heeft uw distributie een andere map).

En als er geen bestanden in de bronmap staan, kan de shell niets vervangen in de plaats van het sterretje, en zal het kopiëren ook mislukken met een fout. Er zijn opties tegen deze situatie failglob и nullglob. We zullen moeten instellen failglob, waardoor de opdracht niet kan worden uitgevoerd. nullglob zal niet werken, omdat het een string met jokertekens die geen overeenkomst heeft gevonden, omzet in een lege string (lengte nul), die cp zal een fout veroorzaken.

Als er echter duizenden bestanden of meer in de map staan, moet de aanpak met jokertekens helemaal worden verlaten. Het feit is dat bash breidt jokertekens uit naar een zeer lange opdrachtregel, zoals:

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

Er is een limiet aan de lengte van de opdrachtregel, die we kunnen achterhalen met behulp van de opdracht:

getconf ARG_MAX

Laten we de maximale lengte van de opdrachtregel in bytes bepalen:

2097152

Или:

xargs --show-limits

We krijgen zoiets als:

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

Laten we het dus helemaal zonder jokertekens doen.

Laten we gewoon schrijven

cp -a /source /target

En hier worden we geconfronteerd met dubbelzinnigheid van gedrag cp. Als de map /target niet bestaat, krijgen we wat we nodig hebben.

Als de doelmap echter bestaat, worden de bestanden gekopieerd naar de map /target/source.

We kunnen de map /target niet altijd vooraf verwijderen, omdat deze bestanden kan bevatten die we nodig hebben en ons doel bijvoorbeeld is om de bestanden in /target aan te vullen met bestanden uit /source.

Als de bron- en doelmappen dezelfde naam hadden, bijvoorbeeld als we aan het kopiëren waren van /source naar /home/source, dan zouden we de opdracht kunnen gebruiken:

cp -a /source /home

En na het kopiëren zouden de bestanden in /home/source worden aangevuld met bestanden uit /source.

Dit is een logisch probleem: we kunnen bestanden toevoegen aan de doelmap als de mappen dezelfde naam hebben, maar als ze verschillend zijn, wordt de bronmap in de doelmap geplaatst. Hoe kopieer ik bestanden van /source naar /target met behulp van cp zonder jokertekens?

Om deze schadelijke beperking te omzeilen, gebruiken we een niet voor de hand liggende oplossing:

cp -a /source/. /target

Degenen die bekend zijn met DOS en Linux hebben alles al begrepen: in elke map bevinden zich 2 onzichtbare mappen “.” en “..”, dit zijn pseudo-mappen die verwijzen naar de huidige en hogere mappen.

  • Bij het kopiëren cp controleert op bestaan ​​en probeert /target/ aan te maken.
  • Zo'n map bestaat en deze is /target
  • Bestanden van /source worden correct gekopieerd naar /target.

Hang het dus in een opvallende lijst ter nagedachtenis of aan de muur:

cp -a /source/. /target

Het gedrag van dit commando is duidelijk. Alles werkt zonder fouten, ongeacht of u een miljoen bestanden heeft of helemaal geen.

Bevindingen

Als u wilt kopiëren alle bestanden van de ene map naar de andere, we gebruiken geen jokertekens, het is beter om ze in plaats daarvan te gebruiken cp gecombineerd met een punt aan het einde van de bronmap. Hiermee worden alle bestanden gekopieerd, inclusief verborgen bestanden, en dit zal niet mislukken als er miljoenen bestanden of helemaal geen bestanden zijn.

nawoord

vmspike stelde een commandoversie voor met een vergelijkbaar resultaat:

cp -a -T /source /target

Oz_Alex

cp -aT /source /target

LET OP: brievenbus T heeft de betekenis. Als je het door elkaar haalt, krijg je complete onzin: de kopieerrichting zal veranderen.
Thanks:

  • vennootschap RUVDS.COM voor ondersteuning en de mogelijkheid om op uw blog op Habré te publiceren.
  • Per afbeelding Drievoudig concept. De afbeelding is zeer groot en gedetailleerd en kan in een apart venster worden geopend.

PS Stuur eventuele fouten die u opmerkt in een privébericht. Ik verhoog mijn karma hiervoor.

cp-opdracht: bestandsmappen correct kopiëren in *nix

Bron: www.habr.com

Voeg een reactie