Đệ quy đổi tên các thư mục con phù hợp với biểu thức chính quy


10

Tôi có một máy chủ phương tiện với một thư mục được gọi Series. ( /media/Expansion2/Series/)

Trong đó, tôi có (bất ngờ!) Phim truyền hình. Đây chỉ là tên chương trình, ví dụ,/media/Expansion2/Series/The Big Bang Theory/

Bên trong mỗi thư mục của chương trình (và đây là vấn đề nằm ở đó) Tôi có các thư mục theo mùa. Tôi hiện đang có một hỗn hợp của 2 quy ước sau (cùng với một vài điều nữa, có lẽ):

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

Cuối cùng, tôi muốn đổi tên tất cả các thư mục thành Season #.

Là một regex, tôi có thể sẽ nói một cái gì đó như s/.*(Season \d)/$1

Chỉ áp dụng cho các thư mục, không phải tập tin. Tôi có lẽ cũng nên đề cập rằng đây là khoảng 50+ thư mục con hiển thị, vì vậy nó cần bắt đầu ở /media/Expansion2/Series/cấp độ và xem xét từng loạt :)

Câu trả lời:


11

Trên Debian và các công cụ phái sinh (bao gồm Ubuntu):

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

Các renamelệnh này là một phần của gói Perl. Nó không được cung cấp bởi các bản phân phối khác, thay vào đó họ cung cấp renamelệnh Linux tiêu chuẩn không hữu ích ở đây.

Nếu rename -n(-không thực sự) hiển thị những gì nó muốn làm, và nó hoàn toàn phù hợp với bạn, hãy bỏ qua -n và thực hiện nó.


Phải nói rằng, tôi đã thấy phương pháp này đặc biệt hữu ích trong vài ngày qua - không chỉ cho các thư mục, mà cả các tệp. Cảm ơn.
Denham Coote

Theo như tôi nhớ, công cụ này được gọi là renametrên Debian chỉ . Trên Ubuntu (& một số hương vị), để tránh xung đột tên với renamelệnh tiêu chuẩn đã đề cập trước đó , đôi khi (nhưng không phải luôn luôn) được tìm thấy bên dưới prename. Ở đây trên Lubfox, bản thân công cụ được gọi prenamenhưng nó có thể được gọi là renamedo chuỗi liên kết tượng trưng /usr/bin/rename -> /etc/alternatives/rename -> /usr/bin/file-rename, trong đó file-renamecó một phiên bản sửa đổi một chút prename.
cú pháp

tuyệt vời! Điều đó khiến tôi làm điều đó cho nhiều tập tin trong nhiều thư mục!
eusoubrasileiro

2

Đoạn mã sau sẽ loại bỏ mọi thứ xảy ra trước lần xuất hiện cuối cùng Season [0-9]trong mỗi thư mục hiển thị bên dưới /media/Expansion2/Series. Không có biểu thức chính quy cần thiết, chỉ là ảm đạm.

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

Nếu bạn thích chơi nó an toàn và chỉ đổi tên some show/some show stuffthành some show/stuff:

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

Nếu bạn muốn tước mọi thứ trước đây Season:

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

${var#PATTERN}dải MẪU ở đầu $varvà trả về kết quả. ${var%PATTERN}làm tương tự ở cuối ${var#PATTERN}${var%PATTERN}loại bỏ tiền tố phù hợp ngắn nhất và hậu tố tương ứng; ${var##PATTERN}${var%%PATTERN}loại bỏ các trận đấu dài nhất.


0

Tôi sẽ đăng thêm hai giải pháp với hy vọng chúng có thể hữu ích trong tương lai. Chúng đến từ các quản trị viên Linux tại nơi làm việc. Chỉ cần đi để cho thấy có bao nhiêu búa sẽ làm việc trên móng tay này!

Giải pháp 1:

Xin chào

Tôi phải đưa ra một vài giả định ở đây, ví dụ, một phần của thư mục có "XXX Season #" sẽ luôn là thư mục "bên ngoài" (nút lá).

Trong mọi trường hợp, tôi sẽ viết một kịch bản nhỏ. Một cái gì đó như thế này sẽ hoạt động (lưu ý các dấu ngoặc kép xung quanh các biến, để đảm bảo bạn nắm bắt tất cả các khoảng trắng trong thư mục):

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

Tất nhiên, trước khi bạn chạy nó bằng lệnh "mv" $ {olddir} "" $ {newdir} "" bạn nên đặt một cái gì đó như "echo" $ {olddir} "" $ {newdir} "" để đảm bảo bạn nhận được kết quả mà bạn mong đợi hoặc bạn có thể kết thúc với một cơn đau đầu khác :-P


Giải pháp 2:

Xin chào

Hầu hết các câu trả lời đã có trong câu hỏi. Dù sao, chạy một cái gì đó như sau từ thư mục Series sẽ hoạt động tốt:

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  


Giải thích:
• find -mindepth 2 -maxdepth 2 -type d (liệt kê các thư mục xuống hai cấp)
• trong khi đọc dir; (lặp trên mỗi thư mục)
• mv -T "$ dir" (di chuyển thư mục nguồn sang ... -T là cần thiết để gặp lỗi nếu các thư mục Mùa không phải là duy nhất tức là bạn không có "Mùa lý thuyết Big Bang 22 "và" Phần 22 "trong cùng thư mục)
• dirname" $ ​​dir "trả về đường dẫn trong đó thư mục là
• tên cơ sở" $ dir "trả về tên của thư mục
• sed" s /. Season ([0-9] ) $ / Season \ 1 / i "hoàn thành phép thuật với regrec không phân biệt chữ hoa chữ thường, chỉ trong trường hợp.

Trong thử nghiệm nhỏ của tôi, nó đã hoạt động (thử trước với tiếng vang trước 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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.