Aplatir la hiérarchie des répertoires en préservant les noms de répertoire dans le nouveau nom de répertoire

7

Je veux essentiellement partir de ceci:

.
├── Alan Walker
│   ├── Different World
│   │   ├── 01 Intro.mp3
│   │   ├── 02 Lost Control.mp3
│   │   └── cover.jpg
│   └── Same World
│       ├── 01 Intro.mp3
│       └── 02 Found Control.mp3
├── Aurora
│   └── Infections Of A Different Kind Step 1
│       ├── 01 Queendom.lrc
│       ├── 02 Forgotten Love.lrc
│       └── 03 Gentle Earthquakes.mp3
└── Guns N' Roses
    └── Use Your Illusion I
        ├── 01 Right Next Door To Hell.lrc
        ├── 01 Right Next Door To Hell.mp3
        ├── 02 Dust N' Bones.lrc
        └── 02 Dust N' Bones.mp3

pour ça:

.
├── Alan Walker - Different World
│   ├── 01 Intro.mp3
│   ├── 02 Lost Control.mp3
│   └── cover.jpg
├── Alan Walker - Same World
│   ├── 01 Intro.mp3
│   └── 02 Found Control.mp3
├── Aurora - Infections Of A Different Kind Step 1
│   ├── 01 Queendom.lrc
│   ├── 02 Forgotten Love.lrc
│   └── 03 Gentle Earthquakes.mp3
└── Guns N' Roses - Use Your Illusion I
    ├── 01 Right Next Door To Hell.lrc
    ├── 01 Right Next Door To Hell.mp3
    ├── 02 Dust N' Bones.lrc
    └── 02 Dust N' Bones.mp3

Aucune des solutions existantes que j'ai pu trouver ne renomme le répertoire lui-même. Ce serait génial de pouvoir le faire avec zmv, mais je ne sais pas comment.

aksh1618
la source
2
Pas une solution complète, donc pas une réponse: easytagpeut vous permettre de le faire, mais uniquement pour les fichiers audio - je ne pense pas que cela déplacera les couvertures, etc.
rvs
2
Pourrait-il y avoir plus d'un album pour un artiste spécifique dans un même répertoire d'artistes? La structure a-t-elle toujours trois niveaux de profondeur?
nohillside
1
@nohillside Oui, il peut y avoir plus d'un album pour un artiste. Et oui, la structure a toujours trois niveaux de profondeur.
aksh1618

Réponses:

9

Zsh

Non testé:

zmv -Q '(*)/(*)(/)' '$1 - $2'
rmdir -- *(/^F)

La deuxième ligne supprime tous les répertoires vides, même ceux qui n'avaient pas de fichier auparavant. Il est possible de contourner cela avec un mvwrapper personnalisé qui enregistre à partir de quels répertoires il déplace les choses.

Notez que cela traverse des liens symboliques vers des répertoires du répertoire courant.

Utilitaire de renommage Linux

Non testé.

rename / ' - ' */*/
rmdir -- */ 2>/dev/null

Notez que cela traverse des liens symboliques vers des répertoires dans le répertoire courant et dans ses sous-répertoires. La deuxième ligne supprime tous les répertoires vides, même ceux qui n'avaient pas de fichier auparavant.

Script de renommage Perl

Non testé.

prename 's~/~ - ~' */*/
rmdir -- */ 2>/dev/null

Notez que cela traverse des liens symboliques vers des répertoires dans le répertoire courant et dans ses sous-répertoires. La deuxième ligne supprime tous les répertoires vides, même ceux qui n'avaient pas de fichier auparavant.

Voici une approche plus complexe qui ne supprime que les répertoires dont elle a renommé quelque chose. Encore une fois, non testé.

prename 's~([^/]+)/~$1 - ~ and ++$d{$1}; END {map {rmdir} keys %d}' */*/
Gilles 'SO- arrête d'être méchant'
la source
12

Quelque chose comme ça peut-être?

#!/bin/sh

for topdir in */; do
    topdir_name=$( basename "$topdir" )

    for subdir in "$topdir"/*/; do
        subdir_name=$( basename "$subdir" )

        newdir="$topdir_name - $subdir_name"
        if mkdir "$newdir"; then
            mv "$subdir"/* "$newdir"
            rmdir "$subdir"
        fi
    done

    rmdir "$topdir"
done

Cela passe par tous les répertoires de niveau supérieur du répertoire actuel (les noms de bande). Pour chacun de ces répertoires, il passe par ses sous-répertoires (les noms d'album). Pour chaque paire de nom de bande et de nom d'album, un nouveau répertoire est créé et les fichiers du sous-répertoire y sont déplacés. Les sous-répertoires d'album sont supprimés lorsqu'ils ont été traités, tout comme les répertoires de niveau supérieur de la bande d'origine.

Les rmdirappels échoueront si un répertoire contient des noms de fichiers cachés ou si l'un des nouveaux répertoires n'a pas pu être créé.

C'est du code totalement non testé. Exécutez-le sur une copie sauvegardée de vos fichiers.

Kusalananda
la source
Je veux dire, oui, quelque chose comme ça fonctionnerait, mais je suis un peu à la recherche d'une solution à une ou deux lignes, pour fonctionner facilement à partir du terminal. Some find / sed / zmv magic :)
aksh1618
10
Mettez ot dans un script, et -boom- cela devient un one-liner.
Hans-Martin Mosner le
4

Stratégiquement, plutôt que de déplacer des fichiers, avez-vous envisagé de laisser la structure actuelle en place et de créer des liens pour la nouvelle structure que vous souhaitez?

Tactiquement, un modèle qui fera le travail se présente comme suit:

find . -mindepth 2 -maxdepth 2 -type d -print0 | xargs -0n1 bash -c \
  'b=$(basename "$(dirname "$1")"); a=$(basename "$1"); echo ln -s "$1" "$b-$a"' {}
  • findlocalise tous les répertoires exactement à deux niveaux de profondeur du répertoire de travail actuel, qui devrait être le répertoire contenant les bandes: ainsi deux niveaux de profondeur sont les noms d'album sous les noms de bande. 1
  • xargs consomme chaque chemin contenant un album et appelle le script bash en ligne.
  • bash -c '...'prend le chemin de l'album comme premier argument, en le divisant en deux parties: le groupe ( $b) et l'album ( $a). Enfin, le script rassemble les noms dans le format souhaité et relie le nouveau nom de répertoire au répertoire d'origine.

Notez que, dans cet exemple, les liens seraient créés dans le même répertoire à partir duquel vous commencez, qui se trouve également être l'endroit où se trouvent les noms de bande.

Vous pouvez - et devriez - modifier la lnstratégie ci-dessus pour qu'elle corresponde à votre intention. mvavec les bons chemins si vous voulez physiquement réorganiser, ou lnsi vous voulez créer une "vue" pratique sur le support. Les parties importantes du script bash sont:

  • $ble nom du groupe. Citer toujours: "$b".
  • $ale nom de l'album. Citer toujours: "$a".
  • $1le chemin d'accès physique au répertoire de l'album. Citer toujours: "$1".

1 Je pense qu'ils m{ax,in}depthsont pris en charge par GNU et certains BSD find, mais pas POSIX: dans ce cas, reposez-vous sur */*ou sur une gymnastique de coque similaire.

évêque
la source
1
J'aime cette réponse ... vous pouvez également créer des liens physiques, puis supprimer l'ancienne structure de dossiers lorsque vous êtes satisfait
Thomas Zwaagstra
@ThomasZwaagstra Ce n'est pas différent que de déplacer les fichiers
Darkhogg
1
@Darkhogg Exactement! OP recherchait une doublure pour déplacer les fichiers. L'utilisation de liens durs avec cette solution y parviendrait presque, sauf que vous auriez une étape intermédiaire de "prévisualisation" avant de supprimer les fichiers originaux
Thomas Zwaagstra