
Cet article révélera certaines choses non évidentes liées à l'utilisation de
caractères génériques lors de la copie, le comportement ambigu de la commande
cp
lors de la copie, ainsi que des moyens de copier correctement un grand nombre de fichiers sans omissions ni plantages.
Supposons que nous devons tout copier du dossier / source vers le dossier / cible.
La première chose qui me vient à l'esprit est:
cp /source/* /target
Corrigez immédiatement cette commande pour:
cp -a /source/* /target
Le commutateur
-a
ajoutera une copie de tous les attributs, droits et ajoutera la récursivité. Lorsqu'une reproduction exacte des droits n'est pas requise, le commutateur
-r
suffit.
Après la copie, nous constatons que tous les fichiers n'ont pas été copiés - les fichiers à partir d'un point comme ont été ignorés:
.profile
.local
.mc
et similaires.
Pourquoi est-ce arrivé?
Parce que les caractères génériques traitent le shell (
bash
dans un cas typique). Par défaut, bash ignorera tous les fichiers commençant par des points, car il les traite comme masqués. Pour éviter ce comportement, nous devons changer le comportement de
bash
utilisant la commande:
shopt -s dotglob
Pour enregistrer ce changement de comportement après un redémarrage, vous pouvez créer le fichier wildcard.sh avec cette commande dans le dossier
/etc/profile.d
(votre distribution peut avoir un dossier différent).
Et s'il n'y a aucun fichier dans le répertoire source, le shell ne peut rien remplacer par l'astérisque et la copie échouera également. Dans ce cas, il existe des
nullglob
failglob
et
nullglob
. Nous devons 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'ont pas trouvé de correspondances en une chaîne vide (de longueur nulle), ce qui provoquera une erreur pour
cp
.
Cependant, s'il y a des milliers de fichiers et plus dans le dossier, l'approche utilisant des caractères génériques doit être complètement abandonnée. Le fait est que
bash
étend 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 limitation sur la longueur de la ligne de commande, que nous pouvons découvrir en utilisant la commande:
getconf ARG_MAX
Obtenez la longueur maximale de la ligne de commande en octets:
2097152
Ou:
xargs --show-limits
Nous obtenons quelque chose comme:
…. Maximum length of command we could actually use: 2089314 ….
Alors, faisons sans aucun caractère générique.
Écrivons juste
cp -a /source /target
Et ici, nous rencontrerons l'ambiguïté du comportement de
cp
. Si le dossier / target n'existe pas, nous obtenons 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 les fichiers dont nous avons besoin et notre objectif, par exemple, est d'ajouter des fichiers à / target avec des fichiers de / source.
Si les dossiers source et de destination étaient nommés de la même manière, par exemple, nous copierions de / source vers / home / source, alors nous pourrions utiliser la commande:
cp -a /source /home
Et après avoir copié les fichiers dans / home / source, les fichiers complétés de / source.
Telle est la tâche logique: nous pouvons ajouter des fichiers au répertoire de destination, si les dossiers sont nommés de la même manière, mais s'ils diffèrent, le dossier source sera placé à l'intérieur du récepteur. Comment copier des fichiers de / source vers / cible en utilisant cp sans caractères génériques?
Pour contourner cette limitation nuisible, nous utilisons une solution non évidente:
cp -a /source/. /target
Ceux qui connaissent bien DOS et Linux ont déjà tout compris: à l'intérieur de chaque dossier il y a 2 dossiers invisibles "." et "..", qui sont des liens de pseudo-dossiers vers les répertoires actuels et supérieurs.
- Lors de la copie,
cp
vérifie l'existence et essaie de créer / cible /. - Un tel répertoire existe et c'est / target
- Fichiers de / source copiés vers / cible correctement.
Ainsi, nous nous accrochons dans un cadre gras dans notre mémoire ou sur le mur:
cp -a /source/. /target
Le comportement de cette commande est sans ambiguïté. Tout fonctionnera sans erreur, que vous ayez un million de fichiers ou pas du tout.
Conclusions
Si vous souhaitez copier
tous les fichiers d'un dossier vers un autre, nous n'utilisons pas de caractères génériques, au lieu d'eux, il est préférable d'utiliser
cp
en combinaison 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 une absence complète de fichiers.
Postface
vmspike a suggéré une variante similaire de la commande:
cp -a -T /source /target
Oz_Alex cp -aT /source /target
ATTENTION: le cas de la lettre
T
compte. Si vous le mélangez, vous obtenez la poubelle complète: le sens de la copie va changer.
Remerciements:
- Société RUVDS.COM pour son soutien et l'opportunité de publier sur son blog sur Habré.
- Par image TripletConcept . L'image est très grande et détaillée, vous pouvez l'ouvrir dans une fenêtre séparée.
Erreurs
PS Direct que vous remarquez dans PM. J'augmente le karma pour cela.
