Rekurencyjnie zmieniaj nazwy podkatalogów pasujących do wyrażenia regularnego

11

Mam serwer multimediów z folderem o nazwie Series. ( /media/Expansion2/Series/)

W nim mam (niespodzianka!) Serial telewizyjny. Są to tylko nazwy programów, np./media/Expansion2/Series/The Big Bang Theory/

W folderze każdego programu (i na tym polega problem) mam foldery sezonu. Obecnie mam mieszankę następujących 2 konwencji (prawdopodobnie wraz z kilkoma innymi):

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

Na koniec chcę zmienić nazwę wszystkich folderów na just Season #.

Jako wyrażenie regularne prawdopodobnie powiedziałbym coś takiego s/.*(Season \d)/$1

Dotyczy tylko folderów, a nie plików. Powinienem chyba również wspomnieć, że dotyczy to ponad 50 podfolderów programów, więc musi zaczynać od /media/Expansion2/Series/poziomu i przeglądać każdą serię :)

Denham Coote
źródło

Odpowiedzi:

12

W przypadku Debiana i pochodnych (w tym Ubuntu):

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

renamePolecenia jest częścią pakietu Perl. Nie są dostarczane przez inne dystrybucje, zamiast tego udostępniają standardowe renamepolecenie Linuksa, które nie jest tu przydatne.

Jeśli rename -n(-nie tak naprawdę) wyświetla to, co chce zrobić, i jest to dla ciebie w porządku, pomiń -n i zrób to.

nieznany użytkownik
źródło
Muszę powiedzieć, że ta metoda była szczególnie przydatna w ciągu ostatnich kilku dni - nie tylko w przypadku folderów, ale także plików. Dzięki.
Denham Coote,
1
O ile pamiętam, narzędzie jest wywoływane tylko wrename Debianie . W systemie Ubuntu (i niektórych odmianach), aby uniknąć kolizji nazw z wcześniej wspomnianym standardowym poleceniem, czasami (choć nie zawsze) można go znaleźć pod . Tutaj na Lubuntu nazywa się samo narzędzie, ale można je wywołać jako ze względu na łańcuch dowiązań symbolicznych , gdzie jest nieco zmodyfikowana wersja . renameprenameprenamerename/usr/bin/rename -> /etc/alternatives/rename -> /usr/bin/file-renamefile-renameprename
składniaerror
niesamowite! To zmusiło mnie do zrobienia tego dla wielu plików w wielu katalogach!
eusoubrasileiro
2

Poniższy fragment usuwa wszystko, co nastąpi przed ostatnim wystąpieniem Season [0-9]w każdym katalogu show w /media/Expansion2/Series. Nie są potrzebne wyrażenia regularne, tylko globusy.

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
jw013
źródło
2

Jeśli wolisz grać bezpiecznie i zmień nazwę tylko some show/some show stuffna some show/stuff:

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

Jeśli chcesz usunąć wszystko wcześniej Season:

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

${var#PATTERN}usuwa WZÓR na początku $vari zwraca wynik. ${var%PATTERN}robi to samo na końcu. ${var#PATTERN}i ${var%PATTERN}usuń odpowiednio najkrótszy pasujący prefiks i sufiks; ${var##PATTERN}i ${var%%PATTERN}usuń najdłuższy mecz.

Gilles „SO- przestań być zły”
źródło
0

Zamierzam opublikować jeszcze dwa rozwiązania w nadziei, że będą one pomocne w przyszłości. Pochodzą one od administratorów Linuksa w pracy. Po prostu pokazuje, ile młotów będzie działać na tym gwoździu!

Rozwiązanie 1:

Cześć Denham,

Muszę tu poczynić kilka założeń, na przykład, że część katalogu z „XXX Season #” zawsze będzie katalogiem „outside” (węzeł liścia).

W każdym razie napisałbym mały skrypt. Coś takiego powinno działać (zwróć uwagę na podwójne cudzysłowy wokół zmiennych, aby uchwycić wszystkie spacje w katalogach):

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

Oczywiście, zanim uruchomisz go za pomocą polecenia „mv” $ {olddir} "" $ {newdir} "", powinieneś umieścić coś takiego jak "echo" $ {olddir} "" $ {newdir} "", aby upewnić się, że jesteś uzyskiwanie oczekiwanych rezultatów lub może wystąpić kolejny ból głowy :-P


Rozwiązanie 2:

Cześć Denham,

Większość odpowiedzi była już w pytaniu. W każdym razie uruchomienie czegoś takiego z folderu Series powinno działać dobrze:

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  


Objaśnienie:
• znajdź -mindepth 2 -maxdepth 2 -typ d (lista katalogów dwa poziomy niżej)
• podczas czytania katalogu ; (zapętlić każdy katalog)
• mv -T „$ katalog” (przenieś katalog źródłowy do ... -T jest potrzebny, aby otrzymać błąd, jeśli foldery sezonu nie są unikalne, tzn. nie masz „The Big Bang Theory Season” 22 ”i„ Sezon 22 ”w tym samym katalogu)

nazwa katalogu „ $ katalog ”zwraca ścieżkę, w której znajduje się katalog
• basename„ $ katalog ”zwraca nazwę katalogu • sed” s /. Sezon ([0–9] ) $ / Season \ 1 / i "uzupełnia magię wyrażeniem regularnym bez rozróżniania wielkości liter, na wszelki wypadek.

W moim małym teście zadziałało (wypróbuj najpierw echo przed 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

Denham Coote
źródło