Mencoba melakukan aritmatika dalam alat rename Perl (Debian)

8

Misalkan saya memiliki lima file mp3:

01-trackfoo.mp3
02-trackbar.mp3
03-trackbaz.mp3
04-trackabc.mp3
05-trackxyz.mp3

Sekarang saya memberikan cepat mendengarkan file (hanya mplayer di konsol akan melakukan trik) dan saya menemukan bahwa trek berada dalam urutan yang salah . 05 sebenarnya 02 dan sisanya harus diganti namanya. Jadi pertama-tama saya akan melakukan perubahan nama:

01-trackfoo.mp3

02-trackbar.mp3
03-trackbaz.mp3
04-trackabc.mp3
00-trackxyz.mp3

Sekarang kita membutuhkan "shift": 02 harus menjadi 03, 03 harus menjadi 04 dan 04 harus menjadi 05. Untuk meminimalkan kebingungan, ex-05 (sekarang 00) baru akan mvdiedit nanti.

Pendekatan saya adalah ini: (perl rename, oleh Larry Wall, default di sini di Debian)

rename 's/0([2-4])([\s\S]+)/0($1+1)$2/' *

juga (nanti, setelah beberapa RTFM'ing)

rename 's/0([2-4])([\s\S]+)/0($1+1)$2/e' *

Tak satu pun dari mereka yang bekerja, terutama karena /e[val]pengubah tidak menerima apa pun selain evaluasi, dan akan membuat kesalahan setelah Anda mencoba untuk menggabungkan evaluasi dengan string. The bashdapat melakukannya dengan baik, misalnya foo$((1+6))akan dievaluasi untuk foo7.

Jadi bagaimana saya bisa melakukan ini (lebih disukai satu-liner, tidak bermaksud untuk menulis seluruh skrip mandiri hanya untuk ini)?

kesalahan sintaks
sumber

Jawaban:

7

Anda hampir memilikinya. Anda hanya perlu membuat string literal dan string secara eksplisit di dalam /esubstitusi -modified, menggunakan tanda kutip dan operator titik.

rename 's/0([2-4])([\s\S]+)/"0".($1+1).$2/e' *
Alan Curry
sumber
Itu membuat 05 asli masih belum diganti namanya, tapi +1 untuk menyelesaikan kesalahan satu-liner .
Peter.O
1
(minor note, rename disebut prename di Ubuntu) ... Jika tidak ada nama dalam direktori dimulai dengan $'\x01'2maka penggantian nama awal seperti ini: prename 's/^05/\x012/' 05*.. lalu [2-4]ganti nama di atas .. maka final prename 's/^\x01/0/' $'\x01'2*akan melakukan trik .. Itu membuat 3 satu -liner ... Untuk pemeriksaan keempat, dan pemeriksaan awal untuk kemungkinan keberadaan file yang dimulai dengan $'\x01', sesuatu seperti cuplikan bash ini akan menjebaknya ..shopt -s nullglob; x=($'\x01'*); [[ -n $x ]] && { echo '\x01' is not suitable; exit; }
Peter.O
YEEES! Terima kasih Alan, saya tidak memikirkan operator titik itu, meskipun saya tahu apa yang harus dilakukan dengan kata-kata yang dapat dibaca manusia: "katakan / e untuk tidak menyentuh barang-barang di luar ()" :) Dan terima kasih kepada Peter untuk bash pendekatan juga. Selain itu, jika saya punya ide tentang seberapa dekat sintaks PHP dengan Perl, saya mungkin akan menemukan solusinya dengan cara coba-coba. Karena titik itu ADALAH rekan JavaScript '+' di PHP untuk penggabungan string.
syntaxerror
4

lebih disukai satu-liner, tidak bermaksud untuk menulis seluruh naskah mandiri hanya untuk ini

Ketika segalanya menjadi rumit, saya tidak melihat alasan untuk tidak menulis skrip. Anda tidak akan pernah ingat bagaimana melakukan ini dari satu menjalankan ke yang berikutnya, sehingga Anda akan berakhir baik menciptakan kembali setiap kali, atau tetap membungkusnya dalam skrip.

Untuk hal kecil seperti ini, saya biasanya mulai mencoba menyelesaikannya di Bash:

#!/bin/bash
if [ -z "$1" ] ; then echo Need arguments. ; exit 1 ; fi

typeset -i i=1
for f in "$*"
do
    tailbits=`echo "$f" | sed -e 's/^[0-9]+//'`
    mv "$f" sertmp-`printf %02d $i`"$tailbits"
    i=i+1
done

for f in "sertmp-*"
do
    mv "$f" `echo "$f" | sed -e s/^sertmp-//` 
done

Pada dasarnya, skrip ini menghapus setiap digit terkemuka, kemudian menempatkan nomor seri yang bertambah nol di bagian depan, dengan file-file bernomor sesuai dengan urutan Anda meneruskannya ke skrip.

Ini dilakukan dalam dua tahap, dengan sertmp-awalan untuk pass pertama untuk menghindari risiko tabrakan nama. Jika Anda memanggil skrip ini mp3-renamerdan menyebutnya seperti:

$ mp3-renamer 01-foo.mp3 03-bar.mp3 04-qux.mp3

Anda mengalami tabrakan sepele pada nama pertama jika Anda tidak menggunakan 2 pass untuk melakukan penggantian nama. ( 01-foo.mp3-> 01-foo.mp3.)

Jika Anda menyebutnya seperti ini, namun:

$ mp3-renamer 02-foo.mp3 01-foo.mp3

Anda secara tidak sengaja menghapus 01-foo.mp3nama pertama dengan nama 1 pass.

Jika masalahnya semakin rumit, saya akan menulis ulang di Perl. Pada titik itu, Anda kemudian dapat menggunakan hash untuk menahan pemetaan nama lama> baru, dan menggunakan sedikit kode pintar untuk mengetahui urutan yang tepat untuk melakukan penggantian nama untuk menghindari kebutuhan 2 pass.

Warren Young
sumber