Commande cp : copier correctement les dossiers de fichiers vers *nix

Commande cp : copier correctement les dossiers de fichiers vers *nix

Cet article dévoilera certaines choses non évidentes liées à l'utilisation de caractères génériques lors de la copie, comportement de commande ambigu cp lors de la copie, ainsi que des méthodes qui vous permettent de copier correctement un grand nombre de fichiers sans sauter ni planter.

Disons que nous devons tout copier du dossier /source vers le dossier /target.

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

cp /source/* /target

Corrigeons immédiatement cette commande en :

cp -a /source/* /target

clé -a ajoutera la copie de tous les attributs, droits et ajoutera la récursivité. Lorsque la reproduction exacte des droits n’est pas requise, une clé suffit -r.

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

.profile
.local
.mc

etc.

Pourquoi est-ce arrivé?

Parce que les caractères génériques sont traités par le shell (bash dans un cas typique). Par défaut, bash ignorera tous les fichiers commençant par des points, car il les traitera comme masqués. Pour éviter ce comportement, nous devrons changer de comportement bash en utilisant la commande :

shopt -s dotglob

Pour garantir que ce changement de comportement persiste après un redémarrage, vous pouvez créer un fichier wildcard.sh avec cette commande dans le dossier /etc/profile.d (Peut-être que votre distribution a un dossier différent).

Et s'il n'y a aucun fichier 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 contre cette situation failglob и nullglob. Nous devrons définir failglob, ce qui empêchera l'exécution de la commande. nullglob ne fonctionnera pas, car il convertit une chaîne avec des caractères génériques qui n'a pas trouvé de correspondance en une chaîne vide (longueur nulle), ce qui pour cp provoquera une erreur.

Cependant, s'il y a des milliers de fichiers ou plus dans le dossier, l'approche des caractères génériques doit être complètement abandonnée. Le fait est que bash développe les caractères génériques 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 connaître à l'aide de la commande :

getconf ARG_MAX

Obtenons la longueur maximale de la ligne de commande en octets :

2097152

Или:

xargs --show-limits

Nous obtenons quelque chose comme :

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

Alors, renonçons complètement aux caractères génériques.

Écrivons simplement

cp -a /source /target

Et nous sommes ici confrontés à une ambiguïté de comportement cp. Si le dossier /target n’existe pas, nous obtiendrons ce dont nous avons besoin.

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

Nous ne pouvons pas toujours supprimer le dossier /target à l'avance, car il peut contenir des fichiers dont nous avons besoin et notre objectif, par exemple, est de compléter les fichiers de /target avec des fichiers de /source.

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

cp -a /source /home

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

C'est un problème logique : nous pouvons ajouter des fichiers dans le répertoire de destination si les dossiers portent le même nom, mais s'ils sont différents, alors le dossier source sera placé à l'intérieur de la destination. Comment copier des fichiers de /source vers /target en utilisant cp sans caractères génériques ?

Pour contourner cette limitation néfaste, nous utilisons une solution non évidente :

cp -a /source/. /target

Ceux qui connaissent DOS et Linux ont déjà tout compris : à l'intérieur de chaque dossier il y a 2 dossiers invisibles "." et « .. », qui sont des pseudo-dossiers liés aux répertoires actuels et supérieurs.

  • Lors de la copie cp vérifie l'existence et essaie de créer /target/.
  • Un tel répertoire existe et c'est /target
  • Les fichiers de /source sont copiés correctement dans /target.

Alors, accrochez-le dans un cadre audacieux dans votre mémoire ou au mur :

cp -a /source/. /target

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

résultats

Si vous devez copier tous fichiers d'un dossier à un autre, nous n'utilisons pas de caractères génériques, il vaut mieux les utiliser à la place cp combiné avec un point à la fin du dossier source. Cela copiera tous les fichiers, y compris ceux cachés, et n'échouera pas avec des millions de fichiers ou aucun fichier du tout.

Postface

vmspike a suggéré une version de commande avec un résultat similaire :

cp -a -T /source /target

Oz_Alex

cp -aT /source /target

REMARQUE : casse des lettres T a le sens. Si vous mélangez les choses, vous obtiendrez des conneries totales : le sens de copie changera.
Merci

  • Les entreprises RUVDS.COM pour du soutien et la possibilité de publier sur votre blog sur Habré.
  • Par image Triple-concept. L'image est très grande et détaillée et peut être ouverte dans une fenêtre séparée.

PS Veuillez envoyer toute erreur que vous remarquez dans un message privé. J'augmente mon karma pour cela.

Commande cp : copier correctement les dossiers de fichiers vers *nix

Source: habr.com

Ajouter un commentaire