Comment déplacer tous les fichiers dans les sous-dossiers actuels ici

8

J'ai également 50 dossiers avec certains sous-dossiers, avec plus de 1000 fichiers audio au total. J'ai besoin de supprimer tous les sous-dossiers et de mettre tous les fichiers au niveau actuel. Essayé mv */* ./mais il se plaint: liste d'arguments trop longue

Pedro Gonzalez
la source

Réponses:

7

Je suppose que l'extension de vos fichiers audio est .mp3

find <AudioFolderPath> -name '*.mp3' -exec mv -it <YourTargetFolder> {} +

Remarques:

  • Remplacez .mp3par l'extension de vos fichiers audio

  • Remplacez-le <AudioParentFolderPath>par le dossier parent qui contient vos sous-dossiers.

  • Remplacez <YourTargetFolder>par le chemin du dossier dans lequel vous devez placer tous les fichiers.

  • Si les fichiers de remorquage de différents sous-dossiers portent le même nom, un seul sera déplacé.

modifier: Comme l'a dit Costas : "Le -icommutateur rend mvinteractif, il vous demandera avant d'écraser les fichiers existants"

Muhammad
la source
'-t' vous permet-il de spécifier la destination en premier? (comme je n'ai pas cette option sur mon "mv" ici, je ne peux que supposer que vous mettez d'abord le dossier de destination puis la liste des fichiers à y déplacer ... mais sinon, cela va essayer de s'adapter à tous dans le dernier nom de fichier, donnant un avertissement) tpourrait être pour "cible"?
Olivier Dulac
Oui, comme vous l'avez dit, -tpermettez de spécifier d'abord la destination. à partir de la mvpage de manuel: -t, --target-directory=DIRECTORY move all SOURCE arguments into DIRECTORY
Muhammad
1
veuillez noter qu'il s'agit de l'option GNU mv, et non disponible sur tous les appareils (dans certains environnements de production, au moins). Je fournis une solution plus portable, mais la vôtre fonctionne bien pour Linux
Olivier Dulac
oui @OlivierDulac, vous avez raison, merci pour votre note.
Muhammad
4
find . -type f -mindepth 2 -exec mv -t ./ {} +

Notez que cette commande écrasera tous les fichiers du même nom. Vous pouvez utiliser ceci pour être invité avant d'écraser:

find . -type f -mindepth 2 -exec mv -it ./ {} +

Explication

  • -type f : ne trouve que les fichiers réguliers.
  • -mindepth 2 : recherche uniquement les fichiers dans les sous-répertoires.
  • -exec mv -it ./ {}: le -execmoyen "exécuter cette commande sur chaque fichier trouvé". Le {}sera remplacé par les noms de fichiers. Le -icommutateur rend mvinteractif, il demandera avant d'écraser les fichiers existants et -tdéfinit le répertoire cible ./.
  • +: mettre les fichiers ensemble (dans une ligne d'argument) autant que le shell peut fonctionner avec la commande pour appeler les temps minimum de commande (pas un par un mais un à plusieurs).

En ce qui concerne les suppressions de dossiers vides, vous pouvez utiliser la même recette:

find . -type d -empty -delete
Costas
la source
1
-type fsélectionne uniquement les fichiers simples, à l'exclusion des liens symboliques, des canaux nommés et similaires. Pour déplacer tous les fichiers autres que les répertoires, vous pouvez le faire ! -type d.
jimmij
@jimmij Je suppose que personne ne stocke les fichiers audio en tant que canal nommé ou autre chose. Si vous vous inquiétez des liens symboliques, vous pouvez utiliser le -Lparamètre
Costas
1
-iest standard, -test uniquement GNU (rien à voir avec Linux qui n'est qu'un noyau trouvé dans certains systèmes GNU et non GNU)
Stéphane Chazelas
Je suis d'accord avec @ StéphaneChazelas: -tn'existe pas sur certains systèmes (comme un AIX pas si ancien)
Olivier Dulac
@OlivierDulac Il est presque impossible de trouver une décision pour satisfaire tout le monde donc les différentes variantes sont les bienvenues. Personne ne vous interdit de changer la chaîne enfind . -type f -mindepth 2 -exec mv {} ./ \;
Costas
2

Oui, c'est une limite sur la taille cumulée des arguments et de l'environnement passés à l' execve()appel système lors de l'exécution d'une commande externe.

Avec zsh, vous pouvez utiliser son intégré à la mvplace:

zmodload -F zsh/files +b:zf_mv
zf_mv ./*/* .

Ou utilisez zargspour diviser la liste en morceaux gérables:

autoload zargs
zargs -Ifiles ./*/* -- mv files .

Avec ksh93:

command -x mv ./*/* .

Avec GNU xargset avec GNU mvavec un shell où printfest intégré (la plupart, mkshétant l'exception notable):

printf '%s\0' ./*/* | xargs -r0 mv -t .
Stéphane Chazelas
la source
N'oubliez pas qu'OP ne veut déplacer que des fichiers, pas des répertoires, vous devez donc vous en occuper. Dans le zshcas où vous pouvez mettre des qualificatifs glob , par exemple (.)ou (^/)après dernier *.
jimmij
0

Une solution assez portable pourrait être:

rechercher tous les fichiers dans tous les sous-dossiers et les déplacer dans le répertoire courant

find ./*/ -type f -print | xargs mv -i "{}" ./

Vous pouvez ajouter un | egrep "\.au$|\.mp3$|\.ac3$"entre les deux pour vous assurer que les fichiers que vous avez trouvés sont des fichiers avec une extension audio (ajoutez autant d'extensions que nécessaire pour couvrir tous les types, je n'en fournis que 3 communs)

Olivier Dulac
la source
Dans votre cas, il n'est pas nécessaire d'appeler finddu tout. Juste assez echoouprintf
Costas
@Costas: l'OP mentionne qu'il y a tellement de fichiers que "*" ne peut pas être développé ... Ici, je développe simplement les 50 noms de dossiers, et le reste est géré par xargs
Olivier Dulac
Mais findne résolvez pas le problème mais xargsfaites-le.
Costas