Bash shell script para localizar y eliminar subcadenas dentro de un nombre de archivo

2

Estoy tratando de escribir una secuencia de comandos de shell bash (llamada por Automator Action) para cambiar el nombre de los programas de televisión en DVD que he llamado mal a lo largo de los años. Quiero eliminar parte del texto en los nombres de archivo. Quiero eliminar el texto que aparece después de una serie específica de caracteres que sé que siempre aparecerán en el nombre del archivo. Pero no sé cuántos caracteres aparecerán antes o después de la serie conocida de caracteres. Tampoco sé si el texto anterior o posterior contendrá múltiples puntos o guiones. Un ejemplo probablemente ayudaría:

The.Big.Bang.Theory.S01E01.xxxxxxxx.mp4

Sé que cada archivo siempre contendrá una cadena en el formato de SxxExx donde las x siempre son números. Pero no sé cuáles serán los números. Quiero obtener el nombre del archivo hasta e incluyendo la cadena SxxExx y la extensión del archivo, pero eliminar todo lo demás. Entonces, para el ejemplo anterior, terminaría con:

The.Big.Bang.Theory.S01E01.mp4

He intentado usar los comandos integrados de reemplazo de cadenas de bash. Pensé que el comando de índice expr me daría el punto de inicio entero de la cadena SxxExx y luego podría usar $ {filename: offset: length} para extraer solo la parte requerida del nombre de archivo (ya sé la extensión para que pueda ser re -adicional). Pero parece que la versión OS X de expr no incluye la funcionalidad de índice. Sólo he hecho scripts en Basic y LotusScript antes. En esos entornos, esto hubiera sido bastante fácil utilizando comandos como 'Me gusta' e 'Instr' o 'Mid'. Pero en el bash simplemente no puedo entenderlo. He pasado horas buscando en Google tratando de entender cómo usar expresiones regulares para ubicar la subcadena 'SxxExx' en el nombre del archivo, pero simplemente no puedo entenderlo. ¡Espero que algunos guionistas inteligentes de UNIX puedan ayudarme!

    
pregunta Stu 22.08.2011 - 12:27

2 respuestas

1
ls | perl -nl -e '/(.*)(S[0-9]+E[0-9]+).*(\.mp4)/ && print "mv \"" . $_ . "\" \"". $1 . $2 . $3 . "\""'

¿Cómo funciona esto? El primer ls genera la lista de archivos, uno por línea, así:

The.Big.Bang.Theory.S01E01.xxxxxxxx.mp4
The.Big.Bang.Theory.S01E02.somecrap.mp4
The.Big.Bang.Theory.S04E12.otherjunk.mp4

Luego, perl -nl divide esto en líneas, alimentando a cada una de las expresiones regulares, como awk *. La expresión regular captura 3 grupos (indicados por paréntesis), primero el bit antes de SxxEyy, luego eso, luego el sufijo del archivo. Luego simplemente ensambla un comando mv adecuado para cambiar el nombre de los archivos, de esta manera:

mv "The.Big.Bang.Theory.S01E01.xxxxxxxx.mp4" "The.Big.Bang.Theory.S01E01.mp4"
mv "The.Big.Bang.Theory.S01E02.somecrap.mp4" "The.Big.Bang.Theory.S01E02.mp4"
mv "The.Big.Bang.Theory.S04E12.otherjunk.mp4" "The.Big.Bang.Theory.S04E12.mp4"

Esto se puede inspeccionar y, una vez que esté satisfecho, haga lo que quiera, canalizándolo en un shell agregando: | sh .

* awk normalmente sería una buena herramienta para esto, pero lamentablemente solo awk de GNU es compatible con los grupos de captura de expresiones regulares y Mac OS X no incluye gawk de forma predeterminada.

    
respondido por el Ingmar Hupp 22.08.2011 - 13:21
3

Sólo con bash:

for filename in *; do
    if [[ "$filename" =~ (.*S[0-9][0-9]E[0-9][0-9]).*(\....)$ ]]; then
        echo mv "$filename" "${BASH_REMATCH[1]}${BASH_REMATCH[2]}"
    fi
done

Elimina el "eco" cuando estés satisfecho de que está funcionando.

    
respondido por el glenn jackman 22.08.2011 - 14:26

Lea otras preguntas en las etiquetas