Comment puis-je rechercher des fichiers dans tous les sous-répertoires à l'aide du shell, puis copier ces fichiers?

8

Comment puis-je trouver uniquement les fichiers * .mp3 avec une commande récursive comme ls -R *.mp3dans un répertoire qui contient plusieurs sous-répertoires et à la fin copier ces fichiers dans un répertoire que je choisis.

Merci pour votre aide.

V 3 L 3 N 0
la source

Réponses:

14

La commande est:

find /path/to/directory -name "*.mp3" -exec cp {} /some/other/dir/ \;

Alternative:

find /path/to/dir/ -name '*.mp3' | xargs cp -t /target/

Exemple:

alex@MaD-pc:~/test$ ls
1  2  3
alex@MaD-pc:~/test$ ls 1 2 3
1:
1.txt  2.mp3  3.txt

2:
4.txt  5.mp3  6.txt

3:
alex@MaD-pc:~/test$ find . -name "*.mp3" -exec cp {} 3/ \;
alex@MaD-pc:~/test$ ls 3
2.mp3  5.mp3

Pour plus d'informations:

man find
hytromo
la source
Les juges accepteraient également:find /path/to/dir/ -name '*.c' | xargs cp -t /target/
Oli
Je suis l'un des juges et je nie cette solution 8-) Merci pour le commentaire, je vais l'ajouter :)
hytromo
1
xargsest normalement beaucoup plus rapide. Je viens de lancer un test rapide ici pour trouver une charge de fichiers c et les exécuter ls -l. C'est 0m2.420s pour xargset 0m25.494s pour -exec... De toute évidence, dans ce cas, l' cpopération va prendre la plupart du temps, donc cela n'a probablement pas d'importance, mais cela vaut la peine d'être noté.
Oli
Je recommanderais d'ajouter la -n`` switch to the commande cp` pour éviter d'écraser dans le cas de noms en double (ou d'écrire un script qui vérifie les doublons avant de copier et de renommer la cible si nécessaire)
Elder Geek
2

Il y a aussi une autre façon de le faire qui, je pense, conviendra parfaitement à votre objectif. Vous pouvez combiner findavec une whileboucle et même pas besoin d'utiliser l'un execou l'autre xargs. Si, par exemple, vous vouliez copier votre mp3sde votre dossier de téléchargement vers votre dossier de musique, vous utiliseriez le script suivant, que j'ai utilisé plusieurs fois.

Vous pouvez le modifier comme vous le souhaitez en changeant les répertoires qui findrecherchent et placent les fichiers résultants; si aucun répertoire n'est indiqué, findrecherche l'ensemble du dossier de départ. Vous pouvez également modifier cpà mvou d' autres commandes. Il est assez rapide car je viens de le tester avec 3945 .jpgfichiers! Copiez-le dans un éditeur de texte, enregistrez-le, puis rendez-le exécutable en exécutant chmod +x myscript.

#!/bin/bash
# a script to recursively find and copy files to a desired location
find ~/Downloads -type f -iname '*.mp3' -print0 |
while IFS= read -r -d '' f; 
do cp -- "$f" ~/Music ;
done

Sur ce wiki Bash noté, il est montré combien il est utile de combiner la whileboucle et les readcommandes pour traiter la sortie de la findcommande; et la façon dont je l'ai fait garantit que le script ne se cassera pas s'il rencontre des noms de fichiers avec des espaces ou d'autres caractères spéciaux inattendus.

Pour des informations plus générales sur la findcommande, entrez dans le terminal man findou consultez les pages de manuel Ubuntu en ligne . Pour une excellente introduction à l'utilisation de find, consultez également cet article .


la source
n'est-ce pas find ~/Downloads -type f -iname '*.mp3' | while read mp3file; do cp "$mp3file" ~/Music; doneplus simple?
steabert
Ma méthode représente les meilleures pratiques et empêche le script de se casser, comme indiqué sur le lien que j'ai cité.
ah, je vois, qui s'occupe de gérer les caractères spéciaux, merci pour le lien :)
steabert
Je recommanderais d'ajouter la -n`` switch to the commande cp` pour éviter d'écraser dans le cas de noms en double (ou d'écrire un script qui vérifie les doublons avant de copier et de renommer la cible si nécessaire)
Elder Geek