Renommer de manière récursive les sous-directorys qui correspondent à une regex

J'ai un server de médias avec un dossier appelé Series . ( /media/Expansion2/Series/ )

En cela, j'ai (surprise!) Série télévisée. Ce ne sont que les noms de spectacles, par exemple, /media/Expansion2/Series/The Big Bang Theory/

Dans le dossier de chaque émission (et c'est là que réside le problème), j'ai des dossiers de saison. J'ai actuellement un mélange des deux conventions suivantes (avec un peu plus, probablement):

  1. /media/Expansion2/Series/The Big Bang Theory/The Big Bang Theory Season 1
  2. /media/Expansion2/Series/The Big Bang Theory/Season 2

En fin de count, je veux renommer tous les dossiers pour seulement Season # .

En regex, je dirais probablement quelque chose comme s/.*(Season \d)/$1

Applicable uniquement aux dossiers, pas aux files. Je devrais probablement aussi mentionner que c'est pour environ 50+ sous dossiers, donc il faut commencer par /media/Expansion2/Series/ level et regarder dans chaque série 🙂

Sur Debian et dérivés (y compris Ubuntu):

 find /media/Expansion2/Series/ -type d -exec rename -n 's/.*(Season \d)/$1/' {} ";" 

La command rename fait partie du packageage Perl. Il n'est pas fourni par d'autres dissortingbutions, mais fournit plutôt la command standard rename Linux qui n'est pas utile ici.

Si rename -n (-pas vraiment) affiche ce qu'il veut faire, et c'est bon pour vous, omettez le -n et faites en sorte qu'il se produise.

L'extrait suivant supprime tout ce qui se produit avant la dernière occurrence de la Season [0-9] dans chaque directory d'exposition sous /media/Expansion2/Series . Pas d'expressions régulières nécessaires, juste des globs.

 cd /media/Expansion2/Series for show in ./*/; do ( cd "$show" || { echo "cd failed. Skipping $show"; exit 1; } for season in ./*Season\ [[:digit:]]*/; do season_prefix=${season%Season [[:digit:]]*} mv "$season" ./"${season#$season_prefix}" done ) done 

Si vous préférez le jouer en toute security et ne renommez que some show/some show stuff séries de some show/some show stuff pour some show/stuff :

 for d in */; do for f in "$d${d%/} *"; do mv "$f" "${d}${f%$d${d%/} }" done done 

Si vous voulez tout dépouiller avant la Season :

 for x in */*Season*; do mv "$x" "${x%/*}/${x##*Season}Season" done 

${var#PATTERN} supprime PATTERN au début de $var et renvoie le résultat. ${var%PATTERN} fait la même chose à la fin. ${var#PATTERN} et ${var%PATTERN} suppriment respectivement le préfixe et le suffixe les plus courts; ${var##PATTERN} et ${var%%PATTERN} suppriment la correspondance la plus longue.

Je vais publier deux autres solutions dans l'espoir qu'elles pourraient être utiles à l'avenir. Ceux-ci venaient des administrateurs Linux au travail. Juste va montrer combien de marteaux vont travailler sur cet ongle!

Solution 1:

Salut Denham,

Je dois faire quelques suppositions ici, par exemple que la partie du directory avec "XXX Season #" sera toujours le directory "outside" (leaf node).

En tout cas, j'écrirais un petit script. Quelque chose comme ça devrait fonctionner (notez les guillemets autour des variables, pour vous assurer de capturer tous les espaces dans les directorys):

 find /media/Expansion2/Series/ -type d | while read olddir do newdir=`echo "${olddir}" | awk -F "/" '$NF ~ /Season/ { last=substr($NF,index($NF, "Season")); while (i<(NF-1)) { i++; printf("/%s", $i) }; printf("/%s\n", last) } $NF !~ /Season/ { print }'` if [ "${olddir}" != "${newdir}" ] then mv "${olddir}" "${newdir}" fi done 

Bien sûr, avant de l'exécuter avec la command "mv" $ {olddir} "" $ {newdir} "" vous devriez mettre quelque chose comme "echo" $ {olddir} "" $ {newdir} get les résultats que vous attendez ou vous pourriez vous refind avec un autre mal de tête 😛

Solution 2:

Salut Denham,

La plupart de la réponse était déjà dans la question. Quoi qu'il en soit, exécuter quelque chose comme le suivant du dossier Series devrait fonctionner correctement:

 find -mindepth 2 -maxdepth 2 -type d | while read dir; do mv -T "$dir" "`dirname "$dir"`/`basename "$dir" | sed "s/.*Season \([0-9]*\)$/Season \1/i"`"; done 

Explication:
• find -mindepth 2 -maxdepth 2 -type d (list des directorys deux niveaux plus bas)
• tout en lisant dir; (boucle sur chaque dir)
• mv -T "$ dir" (déplacez le directory source vers … -T est nécessaire pour get une erreur si les dossiers de saison ne sont pas uniques, c'est à dire que vous n'avez pas "The Big Bang Theory Saison 22" et "Saison 22 "dans le même directory)
• dirname "$ dir" returnne le path où se trouve le directory
• basename "$ dir" renvoie le nom du directory
• sed "s /. Season ([0-9] ) $ / Season \ 1 / i" complète la magie avec une expression rationnelle insensible à la casse, au cas où.

Dans mon petit test cela a fonctionné (essayez d'abord avec un écho avant mv):

someuser@linux-box:/tmp/Series$ find
.
./The Big Bang Theory
./The Big Bang Theory/Season 2
./The Big Bang Theory/Season 2/file1.avi
./The Big Bang Theory/Season 2/file 3.avi
./The Big Bang Theory/Season 2/file2.avi
./The Big Bang Theory/Season 2/file
./The Big Bang Theory/Season 2/3.avi
./The Big Bang Theory/The Big Bang Theory Season 1
./The Big Bang Theory/The Big Bang Theory Season 1/file1.avi
./The Big Bang Theory/The Big Bang Theory Season 1/file 3.avi
./The Big Bang Theory/The Big Bang Theory Season 1/file2.avi
./The Big Bang Theory/The Big Bang Theory Season 1/file
./The Big Bang Theory/The Big Bang Theory Season 1/3.avi
./Other Series
./Other Series/Season 2
./Other Series/Stre dsfdf sd dSeason 3

someuser @ linux-box: / tmp / Série $ find -mindepth 2 -maxdepth 2 -type d | tout en lisant dir; do mv -T "$ dir" " dirname "$dir" / basename "$dir" | sed "s/.*Season \([0-9]*\)$/Season \1/i" "; terminé
mv: ./The Big Bang Theory/Season 2' and ./The Big Bang Theory / Saison 2' sont le même file
mv: ./Other Series/Season 2' and ./Autre série / Saison 2' sont le même file

someuser @ linux-box: / tmp / Séries $ find
.
./La théorie du Big Bang
./The Big Bang Theory / Saison 2
./The Big Bang Theory / Saison 2 / file1.avi
./The Big Bang Theory / Saison 2 / dossier 3.avi
./The Big Bang Theory / Saison 2 / file2.avi
./The Big Bang Theory / Saison 2 / file
./The Big Bang Theory / Saison 2 / 3.avi
./The Big Bang Theory / Saison 1
./The Big Bang Theory / Saison 1 / file1.avi
./The Big Bang Theory / Saison 1 / dossier 3.avi
./The Big Bang Theory / Saison 1 / file2.avi
./The Big Bang Theory / Saison 1 / file
./The Big Bang Theory / Saison 1 / 3.avi
./Autres séries
./Autres séries / Saison 3
./Autres séries / Saison 2