Rinominare in modo ricorsivo le sottodirectory che corrispondono a una regex


10

Ho un server multimediale con una cartella chiamata Series. ( /media/Expansion2/Series/)

In esso, ho (sorpresa!) Serie TV. Questi sono solo i nomi degli spettacoli, ad es./media/Expansion2/Series/The Big Bang Theory/

All'interno della cartella di ogni spettacolo (ed è qui che si trova il problema) ho cartelle di stagione. Al momento ho una combinazione delle seguenti 2 convenzioni (insieme ad alcune altre, probabilmente):

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

Alla fine, voglio rinominare tutte le cartelle in solo Season #.

Come regex, probabilmente direi qualcosa del genere s/.*(Season \d)/$1

Applicabile solo alle cartelle, non ai file. Dovrei probabilmente anche menzionare che questo è per circa 50+ show sottocartelle, quindi deve iniziare a /media/Expansion2/Series/livello e guardare in ogni serie :)

Risposte:


11

Su Debian e derivati ​​(incluso Ubuntu):

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

Il renamecomando fa parte del pacchetto Perl. Non è fornito da altre distribuzioni, forniscono invece il renamecomando Linux standard che non è utile qui.

Se rename -n(-n davvero) mostra cosa vuole fare, ed è tutto a posto per te, ometti -n e fallo accadere.


Devo dire che ho trovato questo metodo particolarmente utile negli ultimi giorni, non solo per le cartelle, ma anche per i file. Grazie.
Denham Coote,

Per quanto ricordo, lo strumento è chiamato solorename su Debian . Su Ubuntu (e alcune versioni), al fine di evitare conflitti di nomi con il comando standard precedentemente citato , a volte (ma non sempre) si trova sotto . Qui su Lubuntu, lo strumento stesso viene chiamato ma può essere chiamato come dovuto alla catena symlink , dove è presente una versione leggermente modificata di . renameprenameprenamerename/usr/bin/rename -> /etc/alternatives/rename -> /usr/bin/file-renamefile-renameprename
syntaxerror

eccezionale! Questo mi ha fatto fare questo per più file in più directory!
eusoubrasileiro,

2

Il frammento seguente rimuove qualsiasi cosa si verifichi prima dell'ultima occorrenza Season [0-9]in ogni directory di show in /media/Expansion2/Series. Non sono necessarie espressioni regolari, solo 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

2

Se preferisci giocare in sicurezza e rinomina solo some show/some show stuffper some show/stuff:

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

Se vuoi rimuovere tutto prima Season:

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

${var#PATTERN}rimuove PATTERN all'inizio $vare restituisce il risultato. ${var%PATTERN}fa lo stesso alla fine. ${var#PATTERN}e ${var%PATTERN}rimuovere rispettivamente il prefisso e il suffisso corrispondenti più brevi; ${var##PATTERN}e ${var%%PATTERN}rimuovi la corrispondenza più lunga.


0

Pubblicherò altre due soluzioni nella speranza che possano essere utili in futuro. Questi venivano dagli amministratori Linux al lavoro. Mostra solo quanti martelli funzioneranno su questo chiodo!

Soluzione 1:

Ciao Denham,

Devo fare alcune ipotesi qui, ad esempio che la parte della directory con "XXX Season #" sarà sempre la directory "outside" (nodo foglia).

In ogni caso, scriverei una piccola sceneggiatura. Qualcosa del genere dovrebbe funzionare (nota le doppie virgolette attorno alle variabili, per assicurarti di catturare tutti gli spazi nelle directory):

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

Naturalmente, prima di eseguirlo con il comando "mv" $ {olddir} "" $ {newdir} "" dovresti inserire qualcosa come "echo" $ {olddir} "" $ {newdir} "" per assicurarti di essere ottenere i risultati che ti aspetti o potresti finire con un altro mal di testa :-P


Soluzione 2:

Ciao Denham,

Gran parte della risposta era già nella domanda. Comunque eseguire qualcosa di simile al seguente dalla cartella Serie dovrebbe funzionare bene:

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  


Spiegazione:
• find -mindepth 2 -maxdepth 2 -type d (elenca le directory con due livelli in basso)
• durante la lettura della directory ; (ciclo su ogni directory)
• mv -T "$ dir" (spostare la directory di origine su ... -T è necessario per ottenere un errore se le cartelle Season non sono univoche, ad esempio non si ha "The Big Bang Theory Season 22 "e" Stagione 22 "nella stessa directory)
• dirname" $ ​​dir "restituisce il percorso in cui si trova la dir
• basename" $ ​​dir "restituisce il nome della directory
• sed" s /. Season ([0-9] ) $ / Season \ 1 / i "completa la magia con regexp senza distinzione tra maiuscole e minuscole, per ogni evenienza.

Nel mio piccolo test ha funzionato (provalo prima con un'eco prima di 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/Series$ 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
mv: ./The Big Bang Theory/Season 2' and./The Big Bang Theory/Season 2' are the same file
mv: ./Other Series/Season 2' and./Other Series/Season 2' are the same file

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/Season 1
./The Big Bang Theory/Season 1/file1.avi
./The Big Bang Theory/Season 1/file 3.avi
./The Big Bang Theory/Season 1/file2.avi
./The Big Bang Theory/Season 1/file
./The Big Bang Theory/Season 1/3.avi
./Other Series
./Other Series/Season 3
./Other Series/Season 2

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.