Comment déplacer récursivement tous les fichiers (y compris cachés) d'un sous-dossier dans un dossier parent dans * nix?

14

C'est une question un peu embarrassante, mais je dois admettre qu'à la fin de ma carrière, j'ai encore des questions sur la commande mv.

J'ai souvent ce problème: je dois déplacer tous les fichiers de façon récursive d'un niveau. Disons que j'ai un dossier foo et une barre de dossiers à l'intérieur. La barre a un désordre de fichiers et de dossiers, y compris des fichiers et des dossiers de points. Comment puis-je déplacer tout dans la barre au niveau foo?

Si foo est vide, je déplace simplement la barre d'un niveau au-dessus, supprime foo et renomme la barre en foo. Une partie du problème est que je ne peux pas comprendre ce qu'est le caractère générique de mv pour «tout, y compris les points». Une partie de cette question est la suivante: existe-t-il une discussion approfondie des caractères génériques que les commandes cp et mv utilisent quelque part (la recherche sur Google n'apporte que des didacticiels très basiques).

programmeur mort
la source

Réponses:

19

Dans Bash (et quelques autres), vous pouvez utiliser l'expansion d'accolade pour accomplir cela en une seule ligne:

mv bar/{,.}* .

La virgule sépare un null et un point, de sorte que la mvcommande voit les noms de fichiers qui correspondent *et.*

En pause jusqu'à nouvel ordre.
la source
cela tente également de déplacer «..», échoue avec le message «la ressource est occupée». Fonctionne néanmoins.
Xananax
3
Suggéré par un utilisateur anonyme:To eliminate the error caused by also matching "." and "..", use this command: mv bar/{,.[!.],..?}* .
HopelessN00b
2

La façon la plus simple de le faire est de le faire en deux commandes, car * ne correspond pas à.

cd /foo
mv bar/* ./
mv bar/.??* ./

Vous ne voulez pas utiliser la barre /.* que j'ai découverte en commettant cette erreur:

rm -rf ./.* 

C'est une mauvaise chose. Quelqu'un veut-il deviner pourquoi? ;-)

Matt Simmons
la source
Je ne pense pas que Bash ou Zsh se développe .*en .et ... Zsh ne me convient pas du moins.
Mikael S
Mikael: Je peux promettre que bash le fait (ou du moins l'a fait), car j'ai dû récupérer les répertoires d'utilisateurs que j'ai supprimés en faisant exactement cela
Matt Simmons
2

Première chose à savoir sur la globalisation - c'est fait par le shell, pas par la commande. Consultez la page de manuel de votre shell pour tous les détails.

Jeff Leyser
la source
2

Celui-ci récolte tous les fichiers des sous-dossiers et les déplace vers le répertoire courant

find . -type f -exec mv -iv \{} . \;

Si vous souhaitez réécrire des fichiers avec le même nom, utilisez

yes y | find . -type f -exec mv -iv \{} . \;
michelek
la source
1

mv .??* *prendra soin de tout sauf du point suivi d'un seul caractère. Si cela est courant pour votre situation, vous pouvez ajouter .[a-zA-Z0-9]*. Cela laissera toujours des fichiers avec des noms tels que .;, .^et .^I(onglet). Si vous avez besoin de tout gérer, vous devrez être un peu plus complexe.

mv .. `ls -f | egrep -v '^.$|^..$'
mpez0
la source
0

Si vous avez une structure de répertoires /foo/bar/et que vous souhaitez déplacer tous les fichiers sous barune étape ci-dessus, allez dans le barrépertoire et tapez ce qui suit:

find . -depth -print0 | cpio --null -pvd ../

En général, je pense que cpio(1)c'est mieux pour ce genre de tâches. Vous pouvez consulter la documentation détaillée en la publiant info cpiodans votre shell.

fim
la source