web-dev-qa-db-fra.com

Comment déplacer tous les fichiers des sous-répertoires de manière récursive dans un seul répertoire?

J'essaie de rassembler tous les fichiers du répertoire actuel et tous les sous-répertoires dans un répertoire. J'essaie quelque chose comme ce qui suit

find -type f -exec mv {} collection/{} \; 

la commande ci-dessus ne fonctionnera pas car le second {} donne le chemin complet, comment puis-je collecter tous les fichiers?

10
Bunny Rabbit

Supprimez le {} de mv, mv le prendra comme répertoire cible en ignorant les répertoires parents:

find -type f -exec mv {} collection/ \;
13
Lekensteyn

Au lieu d'utiliser find (qui fait bien le travail), vous pouvez également utiliser le shell à cette fin.

Dites que vous voulez tous les fichiers de $ PWD à $ DEST. La tentative naturelle serait:

mv $PWD/* $DEST

Comment cela marche-t-il? L'expression "$ PWD/*" se développe aux noms de tous les fichiers de ce répertoire. Cette fonctionnalité du shell s'appelle "globbing". Le dernier argument de mv est le répertoire de destination. Si vous avez beaucoup de fichiers, cela ne fonctionnera pas car la longueur de la ligne de commande est limitée.

Mais la solution pose le problème suivant: elle omet les fichiers de points - ou les fichiers, fichiers et répertoires "cachés" dont le nom commence par un ".". Pour résoudre ce problème, vous devez dire à votre shell d'inclure les fichiers de points lors de la migration. Pour ce faire, utilisez

shopt -s dotglob

lorsque vous utilisez bash (et vous utilisez probablement bash sauf si vous avez modifié la valeur par défaut). Dans ce shell, la commande ci-dessus fonctionnera également pour les fichiers de points.

En passant, dans zsh, vous avez la possibilité de choisir cette option au cas par cas. Pour ce faire, mettez

setopt extendedglob

dans votre .zshrc. Ensuite, vous pouvez utiliser

mv $PWD/*(D) $DEST

pour déplacer tous les fichiers, y compris les fichiers dot. (Le "D" a pour effet d'activer temporairement l'option "GLOB_DOTS").

Maintenant, la question initiale était de déplacer tous les fichiers normaux (pas les répertoires) de tous les sous-répertoires et de leurs sous-répertoires vers un seul répertoire. Ceci peut être accompli avec zsh:

mv $PWD/**/*(D.)

Ici, l'expression **/* fait descendre globalement le globber dans des sous-répertoires. Le D signifie "sélectionne également les fichiers .dot"; le . signifie "sélectionne uniquement les fichiers normaux, pas les répertoires".

5
loevborg