Ganti nama subdirektori yang cocok dengan regex secara rekursif

10

Saya memiliki server media dengan folder bernama Series. ( /media/Expansion2/Series/)

Di dalamnya, saya punya serial TV (kejutan!). Ini hanya nama acara, misalnya,/media/Expansion2/Series/The Big Bang Theory/

Di dalam folder setiap pertunjukan (dan di sinilah masalahnya) saya memiliki folder musim. Saat ini saya memiliki campuran dari 2 konvensi berikut (bersama beberapa lainnya, mungkin):

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

Pada akhirnya, saya ingin mengganti nama semua folder menjadi adil Season #.

Sebagai regex, saya mungkin akan mengatakan sesuatu seperti s/.*(Season \d)/$1

Hanya berlaku untuk folder, bukan file. Saya mungkin juga harus menyebutkan bahwa ini adalah untuk sekitar 50+ show sub folder, jadi harus dimulai pada /media/Expansion2/Series/level dan melihat ke setiap seri :)

Denham Coote
sumber

Jawaban:

11

Tentang Debian dan turunannya (termasuk Ubuntu):

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

The renameperintah bagian dari paket Perl. Ini tidak disediakan oleh distribusi lain, mereka malah menyediakan renameperintah Linux standar yang tidak berguna di sini.

Jika rename -n(-tidak benar-benar) menampilkan apa yang ingin dilakukan, dan itu baik-baik saja untuk Anda, hilangkan -n dan wujudkan.

Pengguna tidak diketahui
sumber
Harus mengatakan, saya telah menemukan metode ini sangat berguna selama beberapa hari terakhir - tidak hanya untuk folder, tetapi juga file. Terima kasih.
Denham Coote
Sejauh yang saya ingat, alat ini dipanggil hanyarename pada Debian . Di Ubuntu (& beberapa rasa), untuk menghindari bentrokan nama dengan perintah standar yang disebutkan sebelumnya , kadang-kadang (tetapi tidak selalu) ditemukan di bawah . Di sini di Lubuntu, alat itu sendiri dipanggil tetapi mungkin disebut karena rantai symlink , di mana adalah versi yang sedikit dimodifikasi . renameprenameprenamerename/usr/bin/rename -> /etc/alternatives/rename -> /usr/bin/file-renamefile-renameprename
syntaxerror
luar biasa! Itu membuat saya melakukan itu untuk banyak file di banyak direktori!
eusoubrasileiro
2

Cuplikan berikut menghapus apa pun yang terjadi sebelum kemunculan terakhir dari Season [0-9]setiap direktori pertunjukan di bawah /media/Expansion2/Series. Tidak perlu ekspresi reguler, cukup gumpal.

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
sumber
2

Jika Anda lebih suka memainkannya dengan aman dan hanya mengganti nama some show/some show stuffmenjadi some show/stuff:

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

Jika Anda ingin menghapus semuanya sebelumnya Season:

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

${var#PATTERN}strip POLA di awal $vardan mengembalikan hasilnya. ${var%PATTERN}melakukan hal yang sama di akhir. ${var#PATTERN}dan ${var%PATTERN}hapus masing-masing awalan dan akhiran pencocokan terpendek; ${var##PATTERN}dan ${var%%PATTERN}hapus kecocokan terpanjang.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
0

Saya akan memposting dua solusi lagi dengan harapan mereka dapat membantu di masa depan. Ini berasal dari admin Linux di tempat kerja. Cukup tunjukkan berapa banyak palu yang bisa digunakan pada paku ini!

Solusi 1:

Hai Denham,

Saya harus membuat beberapa asumsi di sini, misalnya bahwa bagian dari direktori dengan "XXX Season #" akan selalu menjadi direktori "luar" (leaf node).

Bagaimanapun, saya akan menulis naskah kecil. Sesuatu seperti ini seharusnya berfungsi (perhatikan tanda kutip ganda di sekitar variabel, untuk memastikan Anda menangkap semua spasi di direktori):

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

Tentu saja, sebelum Anda menjalankannya dengan perintah "mv" $ {olddir} "" $ {newdir} "" Anda harus meletakkan sesuatu seperti "echo" $ {olddir} "" $ {newdir} "" untuk memastikan Anda mendapatkan hasil yang Anda harapkan atau Anda bisa berakhir dengan sakit kepala lain :-P


Solusi 2:

Hai Denham,

Sebagian besar jawabannya sudah ada di pertanyaan. Bagaimanapun menjalankan sesuatu seperti berikut dari folder Series akan berfungsi dengan baik:

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  


Penjelasan:
• find -mindepth 2 -maxdepth 2 -type d (daftar direktori dua tingkat kebawah)
• saat membaca dir; (loop pada setiap dir)
• mv -T "$ dir" (pindahkan dir sumber ke ... -T diperlukan untuk mendapatkan kesalahan jika folder Musim tidak unik yaitu Anda tidak memiliki "The Big Bang Theory Season 22 "dan" Musim 22 "di direktori yang sama)
• dirname" $ ​​dir "mengembalikan path di mana dir adalah
• basename" $ ​​dir "mengembalikan nama direktori
• sed" s /. Musim ([0-9] ) $ / Musim \ 1 / i "menyelesaikan keajaiban dengan regexp case sensitif, untuk berjaga-jaga.

Dalam tes kecil saya itu berhasil (coba dulu dengan gema sebelum 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
sumber