Linux: Copiez tous les fichiers correspondant au modèle du répertoire et des sous-répertoires dans un répertoire unique

31

Si je voulais copier tous les *.sofichiers de srcvers dstje ferais:

cp src/*.so dst

Cependant, je veux copier tous les *.sofichiers de src et il subdirs de dans dst. Des indices?

Albus Dumbledore
la source

Réponses:

36

Essayer:

find src/ -type f | grep -i so$ | xargs -i cp {} dst
Mike Insch
la source
17
findpeut faire une correspondance de modèle et exécuter des commandes. Il n'est pas nécessaire de find src/ -type f -name '*.so' -exec cp '{}' dst/ ';'
diriger
1
Oui, il peut, cependant, il est souvent plus facile de lire un pipeline, les capacités de correspondance de grepmodèles l'emportent de loin sur les modèles de shell simples utilisés dans le -nameparamètre find. xargsest également beaucoup plus puissant que le -execparamètre find.
Mike Insch
2
La solution de @jaquer est bien meilleure car sur MacOSX, l'utilitaire xargs n'a pas l'option -i. Mais sa solution fonctionne comme un charme.
bialix
Je luttais avec un message d'erreur sur l'argument -i de xargs jusqu'à ce que je lise le commentaire de @bialix concernant la solution de jaquer, qui fonctionnait parfaitement sur mon Mac. Merci
svannoy
Cela créera-t-il des sous-répertoires au besoin?
Lennart Rolland
15

Si vous utilisez Bash, vous pouvez activer l' globstar option shell pour faire correspondre les fichiers et les répertoires de manière récursive:

shopt -s globstar
cp src/**/*.so dst

Si vous devez rechercher des fichiers dont les noms commencent par ., et / ou des fichiers dans et sous les répertoires dont les noms commencent par ., définissez dotglobégalement l' option (par exemple, avec shopt -s dotglob). Vous pouvez les définir tous les deux dans une seule commande:

shopt -s globstar dotglob
jáquer
la source
Ne copie pas les fichiers dans les sous-répertoires commençant par a. en leur nom
rboy
8

J'ai essayé la commande suggérée par Mike:

find src/ -type f | grep -i so$ | xargs -i cp {} dst

mais cela a fini par vider tous les fichiers dans le répertoire dstavec leurs chemins d'accès relatifs perdus.

Pour conserver les chemins relatifs, la commande doit être modifiée comme suit:

find src/ -type f | grep -i so$ | xargs -i cp {} dst/{}
Ilya Druker
la source
7
+1. Cependant, cela suppose que les répertoires correspondant aux chemins source relatifs existent sous dst. Dans le cas contraire, utilisez cp --parents. Assurez-vous également de citer les noms de fichiers. Ainsi: ... | xargs -i cp --parents "{}" dst(notez que le dernier argument de cpest désormais "juste" le répertoire de destination). La commande peut être encore plus court (et probablement plus rapide) en utilisant le -tdrapeau: ... | xargs cp --parents -t dst.
Stephan202
1
@ Stephan202 J'ai dû utiliser... | xargs cp {} --parents -t dst.
warvariuc
pour ceux sur Mac, --parentsn'est pas disponible. J'ai utilisé dittoà sa place: stackoverflow.com/questions/11246070/cp-parents-option-on-mac
Bryan Young
3

Une autre façon de procéder est la suivante:

find src/ -type f -name "*.so" -exec cp {} dst/ \;
Kyriakos
la source
Et cela devrait réduire le nombre de cpprocessus: ... -exec cp -t dst/ {} +.
Kamil Maciorowski
Hé Kamil! Merci pour le commentaire! Pouvez-vous m'expliquer comment votre solution accélère les choses! Toujours prêt à en savoir plus :)
Kyriakos
Lorsque vous terminez -execpar ;, {}est remplacé par un chemin à la fois. Vous obtenez un cpfichier séparé pour chaque fichier. Avec la +syntaxe findremplace {}avec plusieurs résultats (jusqu'à une limite définie par le système de la longueur de la ligne de commande; restriction: {}doit être la dernière chose avant +, donc cp -t). Créer et terminer un processus est une chose relativement coûteuse. Pour cette raison, il est bon de l'utiliser +chaque fois que vous attendez beaucoup de résultats. Dans ce cas, la copie de nombreux fichiers peut prendre beaucoup de temps, de sorte que la différence peut passer inaperçue; néanmoins c'est une bonne pratique.
Kamil Maciorowski
1

Le grep peut être remplacé en utilisant le nom de find :

find src/ -type f -name "*.so" | xargs -i cp {} dst/{}
Th. Thielemann
la source