¿Cómo eliminar los caracteres finales en los nombres de archivo en Bash?

13

Tengo un montón de archivos multimedia como los siguientes:

tvshow.s01e11]Bloodlines.avi
tvshow.s01e12]suffer.avi
tvshow.s01e13]NotMe.avi

Me gustaría cambiarles el nombre a

tvshow.s01e11.avi
tvshow.s01e12.avi
tvshow.s01e13.avi

Intenté usar renombrar, pero evidentemente no obtengo la sintaxis correcta porque falla.

Widgeteye
fuente
Si alguna vez quieres hacer esto en una interfaz gráfica de usuario, krenamees encantador. Tiene todo tipo de opciones poderosas y le muestra lo que hará antes de que realmente lo haga. Incluso podría usarlo para probar patrones que podría usar en bash más tarde.
Joe

Respuestas:

14

En shell, uno podría hacer simplemente:

for x in *]*.avi ; do 
    mv -i "$x" "${x%]*.avi}.avi"
done

El shell puede producir una lista de los nombres de archivo con solo un globo regular, y ${var%pattern}elimina el patrón de coincidencia (más corto) desde el final de la cadena en variable var. Como la extensión final es siempre .avi, simplemente la eliminé con el patrón y la agregué nuevamente. Con las comillas, esto también debería funcionar con nombres de archivos que contienen espacios, comoFancy Name for a Show.s01e01]Asdf.avi

ilkkachu
fuente
@NoviceC el patrón extglob no fue una mala idea. En realidad, algo como ${x/]*([^.])}debería hacer, elimina un paréntesis y cualquier número de puntos no. (aunque falla si hay otros corchetes o puntos, ya que no está bloqueado hasta el final de la cadena)
ilkkachu
Ese es un buen punto. Pero realmente complicaba demasiado el problema cuando debería haber seguido ${x/]*.avi}y simplemente agregué un tipo .avicomo tú. Pero tampoco estaba satisfecho con cómo se romperían los espacios en el nombre (`find . -name '*]*.avi'`). Me complace proporcionar un método de comando unix estándar limitado, ya que cambiar el nombre no lo es, pero esto saca a la mía del agua.
Novato C
2

Esto no es práctico, las otras respuestas son mucho más rápidas y cortas, pero ...

¡Puedes usar PowerShell! Microsoft lo ha abierto recientemente y lo hizo multiplataforma. Para obtener descargas e instrucciones de instalación para su sistema operativo, consulte la sección "Obtener PowerShell" .

Una vez que lo instales, puedes usar este breve script:

Get-ChildItem -File '*]*.avi' | ForEach-Object {
    Rename-Item $_ -NewName (($_.Name -Split ']')[0] + '.avi')
}

Básicamente, pasa por cada objeto en el directorio actual que coincide con un archivo *]*.avi, obtiene la parte antes del corchete, lo .avivuelve a colocar y lo asigna como el nuevo nombre.

Para ejecutarlo directamente desde Bash, use este one-liner semi-golfizado:

powershell -command $'gci -File \'*]*.avi\'|%{rename-item $_ -NewName (($_.Name -Split \']\')[0]+\'.avi\')}'

Cita que se escapa por cortesía de esta respuesta de desbordamiento de pila .

(Probado en Bash en Ubuntu en Windows. Probablemente haya una forma mucho más corta de hacerlo con PowerShell, pero quería mostrar algo que sea comprensible para las personas que no conocen las expresiones regulares).

Ben N
fuente
¡Rube Goldberg estaría orgulloso! Las expresiones regulares son un verdadero PITA para aprender, pero valen la pena muchas veces, incluso en el nivel rudimentario en el que puedo usarlas.
Joe
1

Debian tiene un paquete llamado mmv que también podría estar disponible en otras distribuciones, y si no es así, debería ser lo suficientemente fácil de compilar desde la fuente. Te permite escribir esto:

mmv '*]*.avi' '#1.avi'

Puede leer la página de manual de Ubuntu para este comando para obtener más detalles.

MvG
fuente
0

Esto buscará el patrón y reemplazará el texto usando sed.

 $sed 's/\(.*]\)[a-zA-z0-9].*\(.avi\)/\1\2/' filename
Tejender Mohan
fuente