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).

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.*


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? ;-)


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.


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 \{} . \;

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 '^.$|^..$'

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.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.