
In dit artikel worden enkele minder voor de hand liggende zaken met betrekking tot het gebruik van bij het kopiëren, het onduidelijke gedrag van de cp kopieeropdracht en methoden om een groot aantal bestanden correct te kopiëren zonder over te slaan of fouten.
Stel dat we alles willen kopiëren van de map /source naar de map /target.
Het eerste wat in je opkomt is:
cp /source/* /targetLaten we deze opdracht meteen verbeteren naar:
cp -a /source/* /target Sleutel -a voegt het kopiëren van alle eigenschappen toe, behoudt permissies en voegt recursie toe. Wanneer exacte weergave van rechten niet nodig is, is de sleutel -r.
Na het kopiëren zullen we merken dat niet alle bestanden zijn gekopieerd; bestanden die beginnen met een punt, zoals:
.profiel
.lokaal
.mc
en dergelijke, zijn genegeerd.
Waarom is dit gebeurd?
Omdat wildcards door de shell wordt verwerkt (bash in de typische situatie). Standaard negeert bash alle bestanden die beginnen met punten, aangezien deze als verborgen worden beschouwd. Om dit gedrag te voorkomen, moeten we de configuratie wijzigen bash met de opdracht:
shopt -s dotglob Om deze wijziging permanent te maken na een herstart, kun je een bestand wildcard.sh maken met deze opdracht in de map /etc/profile.d (mogelijk is de map anders in jouw distributie).
Als er geen bestanden in de bronmap zijn, kan de shell niets vervangen voor de wildcard en zal het kopiëren ook met een fout eindigen. Voor een dergelijke situatie zijn er opties failglob en nullglob. We moeten failglob, instellen, zodat de opdracht niet kan worden uitgevoerd. nullglob is niet geschikt, omdat deze de string met wildcards zonder overeenkomsten omzet in een lege string (nul-lengte), wat voor cp een fout zal veroorzaken.
Echter, als er duizenden bestanden in de map staan, is het beter om helemaal af te zien van het gebruik van wildcards. Dit komt omdat bash de wildcards omzet in een zeer lange opdrachtregel die eruitziet als:
cp -a /source/a /source/b /source/c …… /targetEr is een limiet aan de lengte van de opdrachtregel die we kunnen achterhalen met de opdracht:
getconf ARG_MAXWe krijgen de maximale lengte van de opdrachtregel in bytes:
2097152Of:
xargs --show-limitsWe krijgen iets als:
….
Maximale lengte van de opdracht die we eigenlijk konden gebruiken: 2089314
….Dus laten we helemaal zonder wildcards werken.
Laten we gewoon schrijven
cp -a /source /target En hier stuiten we op onduidelijk gedrag. cp. Als de map /target niet bestaat, krijgen we precies wat we nodig hebben.
Echter, als de map target bestaat, worden de bestanden gekopieerd naar de map /target/source.
We cannot always delete the folder /target in advance, as it may contain files we need and our goal, for instance, is to add files from /source to /target.
If the source and destination folders had the same names, for example, if we were copying from /source to /home/source, we could use the command:
cp -a /source /homeAnd after copying, the files in /home/source would have been supplemented with files from /source.
Here’s a logical puzzle: we can supplement files in the destination directory if the folders are named the same, but if they differ, the source folder will be placed inside the destination. How to copy files from /source to /target using cp without wildcards?
To bypass this harmful limitation, we use a non-obvious solution:
cp -a /source/. /targetThose familiar with DOS and Linux already understand everything: inside each folder, there are 2 invisible folders, '.' and '..', which are pseudo-link folders for the current and parent directories.
- When copying
cpit checks for existence and tries to create /target. - That directory exists and it is /target.
- Files from /source have been correctly copied to /target.
So, let’s put it in a bold frame in our memory or on the wall:
cp -a /source/. /target
The behavior of this command is unequivocal. Everything will work without errors, regardless of whether you have a million files or none at all.
Conclusies
If you need to copy all files from one folder to another, do not use wildcards; instead, it is better to use cp in combination with a dot at the end of the source folder. This will copy all files, including hidden ones, and will not crash with millions of files or the complete absence of files.
Naschrift
suggested a similar result with the command:
cp -a -T /source /target
cp -aT /source /target WARNING: Case sensitivity T matters. If you mix them up, you will get complete nonsense: the direction of copying will change.
Thanks to:
- The company for the support and the opportunity to publish in their blog on Habra.
- For the image . The image is very large and detailed; you can open it in a separate window.
P.S. Report any noticed errors privately. I will raise your karma for this.
Bron: habr.com
