Commande cp : copie correcte de répertoires avec fichiers sous *nix

Commande cp : copie correcte de répertoires avec fichiers sous *nix

Cet article révélera certaines choses non évidentes liées à l'utilisation des wildcards lors de la copie, le comportement ambigu de la commande cp lors de la copie, ainsi que des méthodes permettant de copier correctement un grand nombre de fichiers sans omissions ni erreurs.

Supposons que nous devions copier tout depuis le dossier /source vers le dossier /target.

La première chose qui vient à l'esprit est :

cp /source/* /target

Correctons cette commande en :

cp -a /source/* /target

Clé -a cela ajoutera la copie de tous les attributs, des permissions et ajoutera la récursivité. Lorsque la reproduction exacte des permissions n'est pas nécessaire, la clé -r.

Après la copie, nous découvrirons que tous les fichiers n'ont pas été copiés - les fichiers commençant par un point ont été ignorés, comme :

.profil
.local
.mc

et similaires.

Pourquoi cela s'est-il produit ?

Parce que les wildcards sont traitées par le shell (bash dans un cas typique). Par défaut, bash ignore tous les fichiers qui commencent par un point, car ils sont considérés comme cachés. Pour éviter ce comportement, nous devrons modifier le comportement bash avec la commande :

shopt -s dotglob

Pour que ce changement de comportement soit conservé après un redémarrage, vous pouvez créer un fichier wildcard.sh avec cette commande dans le dossier /etc/profile.d (peut-être qu'un autre dossier dans votre distribution).

Et s'il n'y a pas de fichiers dans le répertoire source, le shell ne pourra rien substituer à l'astérisque, et la copie échouera également avec une erreur. Il existe des options pour prévenir une telle situation failglob et nullglob. Nous devrons définir failglob, ce qui empêchera la commande de s'exécuter. nullglob ne conviendra pas, car elle transforme la chaîne avec des wildcards n'ayant pas de correspondances en une chaîne vide (de longueur nulle), ce qui entraînera une erreur pour cp .

Cependant, s'il y a des milliers de fichiers dans le dossier, il vaut mieux abandonner l'approche utilisant les wildcards. En effet, bash développe les wildcards en une très longue ligne de commande, comme :

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

Il y a une limite à la longueur de la ligne de commande, que nous pouvons découvrir en utilisant la commande :

getconf ARG_MAX

Nous obtiendrons la longueur maximale de la ligne de commande en octets :

2097152

Ou :

xargs --show-limits

Nous obtiendrons quelque chose comme :

….
Longueur maximale de la commande que nous pourrions réellement utiliser : 2089314
….

Ainsi, essayons de nous passer complètement des wildcards.

Écrivons simplement

cp -a /source /target

Et là, nous nous heurterons à l'ambiguïté du comportement cp. Si le dossier /target n'existe pas, nous obtiendrons ce que nous voulons.

Cependant, si le dossier target existe, les fichiers seront copiés dans le dossier /target/source.

Il n'est pas toujours possible de supprimer à l'avance le dossier /target, car il peut contenir des fichiers nécessaires, et notre objectif est, par exemple, de compléter les fichiers dans /target avec ceux de /source.

Si les dossiers source et destination avaient le même nom, par exemple, si nous copions de /source vers /home/source, nous pourrions utiliser la commande :

cp -a /source /home

Et après la copie, les fichiers dans /home/source seraient complétés avec les fichiers de /source.

Voici un petit problème logique : nous pouvons compléter les fichiers dans le répertoire de destination si les dossiers ont le même nom, mais s'ils diffèrent, le dossier source sera placé à l'intérieur du dossier de destination. Comment copier les fichiers de /source vers /target avec cp sans utiliser de wildcard ?

Pour contourner cette contrainte gênante, nous utilisons une solution peu évidente :

cp -a /source/. /target

Ceux qui connaissent bien DOS et Linux ont déjà compris : chaque dossier possède deux dossiers invisibles « . » et « .. », qui sont des pseudo-dossiers liant le répertoire actuel et le répertoire parent.

  • Lors de la copie cp la commande vérifie l'existence et tente de créer /target.
  • Ce répertoire existe et c'est /target
  • Les fichiers de /source ont été copiés correctement dans /target.

Alors, gravons dans notre mémoire ou sur un mur :

cp -a /source/. /target

Le comportement de cette commande est clair. Tout fonctionnera sans erreurs, que vous ayez un million de fichiers ou aucun.

Conclusions

Si vous devez copier tout des fichiers d'un dossier à un autre, n'utilisez pas de wildcards ; il vaut mieux utiliser cp en combinaison avec un point à la fin du dossier source. Cela copiera tous les fichiers, y compris les fichiers cachés, et ne plantera pas avec des millions de fichiers ou en l'absence totale de fichiers.

Postface

vmspike proposé une variante de commande ayant un résultat similaire :

cp -a -T /source /target

Oz_Alex

cp -aT /source /target

ATTENTION : la casse des lettres des a son importance. Si vous vous trompez, vous obtiendrez une grosse erreur : la direction de la copie changera.
Remerciements :

  • Les entreprises RUVDS.COM pour le soutien et la possibilité de publication sur mon blog sur Habré.
  • Pour l'image TripletConcept. L'image est très grande et détaillée, vous pouvez l'ouvrir dans une fenêtre séparée.

P.S. Veuillez envoyer toute erreur constatée en message privé. Je fais augmenter ma karma pour cela.

Commande cp : copie correcte de répertoires avec fichiers sous *nix

Source : habr.com

Acheter un hébergement fiable pour les sites avec protection DDoS, serveurs VPS VDS 🔥 Acheter un hébergement fiable pour les sites avec protection DDoS, serveurs VPS VDS | ProHoster