Copiez tous les fichiers avec une certaine extension de tous les sous-répertoires

112

Sous unix, je souhaite copier tous les fichiers avec une certaine extension (tous les fichiers Excel) de tous les sous-répertoires vers un autre répertoire. J'ai la commande suivante:

cp --parents `find -name \*.xls*` /target_directory/

Les problèmes avec cette commande sont:

  • Il copie également la structure des répertoires, et je ne veux que les fichiers (donc tous les fichiers doivent se retrouver dans / target_directory /)

  • Il ne copie pas les fichiers avec des espaces dans les noms de fichiers (qui sont assez nombreux)

Des solutions à ces problèmes?

Abdel
la source
Et quoi find... exec mv?
fedorqui 'SO arrêtez de nuire'
Copie

Réponses:

174

--parents copie la structure des répertoires, vous devriez donc vous en débarrasser.

La façon dont vous avez écrit ceci, les findexécutions et la sortie sont placées sur la ligne de commande de telle sorte que cpvous ne pouvez pas faire la distinction entre les espaces séparant les noms de fichiers et les espaces dans le nom de fichier. Il vaut mieux faire quelque chose comme

$ find . -name \*.xls -exec cp {} newDir \;

dans lequel cpest exécuté pour chaque nom de fichier qui findtrouve et transmis correctement le nom de fichier. Voici plus d'informations sur cette technique.

Au lieu de tout ce qui précède, vous pouvez utiliser zsh et taper simplement

$ cp **/*.xls target_directory

zsh peut étendre les jokers pour inclure des sous-répertoires et rend ce genre de chose très facile.

Brian Agnew
la source
2
Oui. «bin it» signifie le jeter. Maintenant modifié :-)
Brian Agnew
13
Bash4.0+ et ksh93prend également en charge **. Pour bash, utilisez shopt -s globstarpour l'activer. Pour ksh, c'est set -Gou set -o globstar.
pynexj
2
@Daryl - J'ai complété davantage. Mais la réponse était déjà marquée comme `` acceptée '', note
Brian Agnew
5
Cet exécutable est techniquement moins efficace que de passer dans xargs, qui fera tout cela en aussi peu d'appels cp que possible: find . -name '*.xls' -print0 | xargs -0 cp -t destdir
Taywee
2
@BrianAgnew Oh, je suis sûr, juste bien d'avoir des informations supplémentaires dans les commentaires pour les googleurs rebelles.
Taywee
37

De tout ce qui précède, j'ai trouvé cette version. Cette version fonctionne également pour moi dans le terminal de récupération mac.

find ./ -name '*.xsl' -exec cp -prv '{}' '/path/to/targetDir/' ';'

Il cherchera dans le répertoire courant et de manière récursive dans tous les sous-répertoires les fichiers avec l'extension xsl. Il les copiera tous dans le répertoire cible.

Les indicateurs cp sont:

  • p - conserver les attributs du fichier
  • r - récursif
  • v - verbeux (vous montre ce qui est copié)
guya
la source
1
C'est la même chose que ce que j'ai dû faire lorsque SSH est entré dans Bluehost.
Plummer
4
Il ne préserve PAS les sous-répertoires.
b005t3r
3
@ b005t3r c'est par conception, ce n'est pas censé le faire. C'était tout l'objet de la question du PO. Il voulait que tous les fichiers des sous-répertoires soient copiés dans un répertoire sans sous
répertoires
2
Existe-t-il un moyen de modifier cela pour conserver les sous-répertoires?
Matthew Dean
8

J'avais un problème similaire. Je l'ai résolu en utilisant:

find dir_name '*.mp3' -exec cp -vuni '{}' "../dest_dir" ";"

Le '{}'et ";"exécute la copie sur chaque fichier.

stingMantis
la source
3

Je devais aussi le faire moi-même. Je l'ai fait via l'argument --parents pour cp:

find SOURCEPATH -name filename*.txt -exec cp --parents {} DESTPATH \;
Ce mec
la source
1
find [SOURCEPATH] -type f -name '[PATTERN]' | 
    while read P; do cp --parents "$P" [DEST]; done

vous pouvez supprimer les --parents mais il y a un risque de collision si plusieurs fichiers portent le même nom.

Camion
la source