Intentando hacer aritmética en la herramienta de cambio de nombre de Perl (Debian)

8

Supongamos que tengo cinco archivos mp3:

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

Ahora escucho rápidamente los archivos (solo mplayer en la consola hará el truco) y descubro que las pistas están en el orden incorrecto . 05 es en realidad 02 y el resto deberá ser renombrado. Así que primero haré un cambio de nombre temporal:

01-trackfoo.mp3

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

Ahora necesitamos un "turno": 02 debería convertirse en 03, 03 debería convertirse en 04 y 04 debería convertirse en 05. Para minimizar la confusión, ex-05 (ahora 00) será mveditado más tarde.

Mi enfoque fue este: (Perl rename, por Larry Wall, predeterminado aquí en Debian)

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

así como (más tarde, después de un poco más de RTFM)

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

Ninguno de ellos trabajó, sobre todo porque el /e[val]modificador no acepta ninguna otra cosa , pero las evaluaciones, y generará un error una vez que se intenta combinar las evaluaciones con cuerdas. El bashpuede hacerlo bien, por ejemplo foo$((1+6)), será evaluado foo7.

Entonces, ¿cómo puedo hacer esto?

error de sintaxis
fuente

Respuestas:

7

Casi lo tienes. Solo necesita hacer explícitas las cadenas literales y la concatenación de cadenas dentro de la /esustitución modificada, utilizando comillas y el operador de punto.

rename 's/0([2-4])([\s\S]+)/"0".($1+1).$2/e' *
Alan Curry
fuente
Deja el 05 original sin cambiar el nombre, pero +1 para resolver el error de una sola línea .
Peter.O
1
(nota menor, el cambio de nombre se llama prename en Ubuntu) ... Si no hay nombres en el directorio que comiencen con $'\x01'2un cambio de nombre preliminar como este: prename 's/^05/\x012/' 05*... entonces el [2-4]cambio de nombre anterior ... entonces una final prename 's/^\x01/0/' $'\x01'2*hará el truco ... Eso hace 3 uno -liners ... Por un cuarto, y una comprobación inicial de la posible presencia de un archivo que comienza $'\x01', algo como este fragmento de bash lo atrapará ...shopt -s nullglob; x=($'\x01'*); [[ -n $x ]] && { echo '\x01' is not suitable; exit; }
Peter.O
SÍ! Gracias Alan, no pensé en ese operador de puntos, aunque sí sabía qué hacer con palabras legibles para humanos: "dile a / e que no toque las cosas fuera del ()" :) Y gracias a Peter por la fiesta enfoque también. Además, si hubiera tenido alguna idea de cuán cercana es la sintaxis PHP a la de Perl, probablemente habría encontrado la solución por prueba y error. Porque ese punto ES la contraparte JavaScript '+' en PHP para la concatenación de cadenas.
syntaxerror
4

one-liner preferido, sin la intención de escribir un script independiente completo solo para esto

Cuando las cosas se ponen tan complicadas, no veo ninguna razón para no escribir un guión. Nunca vas a recordar cómo hacer esto de una carrera a la siguiente, por lo que terminarás reinventándolo cada vez o envolviéndolo en un script de todos modos.

Para una cosa pequeña como esta, generalmente empiezo a tratar de resolverlo en 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

Básicamente, este script elimina todos los dígitos iniciales, luego coloca un número de serie creciente con relleno de cero en el frente, con los archivos numerados de acuerdo con el orden en que los pasa al script.

Lo hace en dos etapas, con sertmp-prefijos para la primera pasada para evitar cualquier riesgo de colisiones de nombres. Si llama a este script mp3-renamery lo llama así:

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

te encuentras con una colisión trivial en el primer cambio de nombre si no usas 2 pases para cambiar el nombre. ( 01-foo.mp3-> 01-foo.mp3.)

Sin embargo, si lo llamas así:

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

accidentalmente borra 01-foo.mp3en el primer cambio de nombre con un cambio de nombre de 1 pasada.

Si el problema se complica, lo reescribiría en Perl. En ese punto, podría usar un hash para mantener la asignación de nombre antiguo-> nuevo, y usar un poco de código inteligente para calcular el orden correcto para hacer las rebajas para evitar la necesidad de 2 pases.

Warren Young
fuente