Cambio de nombre masivo, versión * nix

11

Estaba buscando una manera de cambiar el nombre de una gran cantidad de archivos con nombres similares , como este (una pregunta relacionada con Windows), excepto que estoy usando * nix (Ubuntu y FreeBSD, por separado). Solo para resumir, mientras uso el shell (Bash, CSH, etc.), ¿cómo cambio el nombre en masa de una cantidad de archivos tales como, por ejemplo, los siguientes archivos:

Beethoven - Fur Elise.mp3
Beethoven - Moonlight Sonata.mp3
Beethoven - Oda a la Alegría.mp3
Beethoven - Rage Over the Lost Penny.mp3

será renombrado como estos?

Fur Elise.mp3
Moonlight Sonata.mp3
Oda a la alegría.mp3
Rage Over the Lost Penny.mp3

La razón por la que quiero hacer esto es que esta colección de archivos irá bajo un directorio llamado "Beethoven" (es decir, el prefijo de los nombres de archivo), y tener esta información en el nombre del archivo será redundante.

Paolo B.
fuente

Respuestas:

12

La utilidad de cambio de nombre hará lo que quieras.

Solo usa rename 's/Beethoven\ -\ //g' *.mp3


fuente
¿Puede editar para proporcionar un enlace a la utilidad, o es estándar en ambas distribuciones mencionadas (Ubuntu y FreeBSD)?
Chris W. Rea
1
Viene con Perl. Debian lo usa como comando de cambio de nombre, por lo que sospecho que Ubuntu también lo hace. Hay otro comando 'renombrar' que no vale nada, así que revise la página del manual.
derobert
wow, la sintaxis de cambio de nombre se parece mucho a vim replace: D
Dzung Nguyen
el puerto en / usr / ports / sysutils / rename funcionó perfectamente en FreeBSD
Josh W.
10

Como tantas otras cosas con Linux / Unix, ¡hay más de una forma de hacerlo!

Algunos pueden usar mmv (mv de masa).

El comando rename o prename que viene con algunos paquetes de Perl (Ubuntu y Debian más nuevos) también puede hacer esto.

prename 's/Beethoven\ -\ //g' Beethoven*.mp3

Tenga en cuenta que la herramienta de cambio de nombre en Fedora 10 no es el mismo programa que este y funciona de manera diferente. Es parte de un paquete diferente, util-linux-ng y se puede encontrar aquí .

A menudo solo voy al shell por bucle por costumbre (después de todas esas herramientas no siempre existieron).

mkdir -p Beethoven
for x in Beethoven\ -\ *
do
mv "$x" Beethoven/"${x/Beethoven - /}"
done

Esto creará el directorio de Beethoven, luego moverá el archivo a ese directorio / nombre de archivo, donde el nombre de archivo tiene el "Beethoven -" reemplazado por nada.

Como prueba, antes:

$ ls
Beethoven - Fur Elise.mp3                 Beethoven - Ode to Joy.mp3
Beethoven - Moonlight Sonata.mp3          Beethoven - Rage Over the Lost Penny.mp3

Después:

$ ls Beethoven/
Fur Elise.mp3                 Ode to Joy.mp3
Moonlight Sonata.mp3          Rage Over the Lost Penny.mp3
jtimberman
fuente
4

Pruebe esta solución, implementada usando una combinación de grep y renombrar. Esto supone que tiene un montón de directorios que necesita cambiar de nombre. Si solo hay unos pocos, seguiría el enfoque manual, con el patrón "Artista -" codificado para cada uno.

# Rename any mp3 files in the directory hierarchy of type "a - b.mp3" to "b.mp3"
find . -name "*.mp3" -exec rename -n -v 's|^(.*/).*-\s*(.*)\s*$|$1$2|g' {} \;

Explicación de find :
el comando find encuentra todos los archivos con extensión .mp3 en la jerarquía de archivos actual y llama al argumento pasado a -exec para cada uno. Tenga en cuenta que dentro de -exec , {} se refiere al argumento pasado por find (ruta del archivo + nombre). Las \;asegura que el ;se transfieren a cambiar el nombre y el lugar de indicar el final del hallazgo de comandos.

El comando dado anteriormente tiene el modificador -n (sin acción); por lo tanto, solo le dirá qué sucedería si lo ejecutara. Le recomiendo que ejecute este comando sin el modificador -n solo después de haberlo ejecutado una vez y esté satisfecho con los resultados propuestos.

Ahora para la expresión regular.

  • ^ coincide con el inicio de la cadena.
  • $ coincide con el final de la cadena.
  • . coincide con cualquier personaje.
  • *significa cero o más de la construcción anterior. Por ejemplo, .*significa cero o más caracteres.
  • \s representa cualquier personaje espacial.
  • \S significa cualquier personaje que no sea espacial.
  • Cualquier cosa dentro ()es capturado y se refleja como $1, $2en función de su posición.

La expresión regular:

  • Busca una estructura de directorio opcional al inicio, captura esto en $ 1: (.*/)
  • Salta todo hasta el " -":.*-
  • Captura el resto de la cadena, excepto los espacios iniciales y finales, en $ 2: (.*)
  • Reescribe el archivo como $ 1 $ 2, que debe ser "/path/to/file/""filename.mp3"

Aquí está mi prueba de funcionamiento:

/tmp/test$ ls -R
.:
a  b  c  z-unknown.mp3

./a:
a3.mp3                 a - longer title3.mp3  c.mp3   disc2
a - longer title2.mp3  a - long title.mp3     disc 1  the band - the title.mp3

./a/disc 1:
a - title1.mp3  a - title2.mp3

./a/disc2:
a - title1.mp3  a - title2.mp3

./b:
cd - ab - title3.mp3  cd - title1.mp3  cd - title2.mp3  c.mp3

./c:
c-pony2.mp4  c - pony3.mp3  c - pony4.mp3  c-pony.mp3

/tmp/test$ find . -name "*.mp3" -exec rename -v 's|^(.*/).*-\s*(.*)\s*$|$1$2|g' {} \;
./c/c-pony.mp3 renamed as ./c/pony.mp3
./c/c - pony4.mp3 renamed as ./c/pony4.mp3
./c/c - pony3.mp3 renamed as ./c/pony3.mp3
./z-unknown.mp3 renamed as ./unknown.mp3
./a/the band - the title.mp3 renamed as ./a/the title.mp3
./a/a - longer title2.mp3 renamed as ./a/longer title2.mp3
./a/a - longer title3.mp3 renamed as ./a/longer title3.mp3
./a/disc 1/a - title1.mp3 renamed as ./a/disc 1/title1.mp3
./a/disc 1/a - title2.mp3 renamed as ./a/disc 1/title2.mp3
./a/a - long title.mp3 renamed as ./a/long title.mp3
./a/disc2/a - title1.mp3 renamed as ./a/disc2/title1.mp3
./a/disc2/a - title2.mp3 renamed as ./a/disc2/title2.mp3
./b/cd - title1.mp3 renamed as ./b/title1.mp3
./b/cd - title2.mp3 renamed as ./b/title2.mp3
./b/cd - ab - title3.mp3 renamed as ./b/title3.mp3

/tmp/test$ ls -R
.:
a  b  c  unknown.mp3

./a:
a3.mp3  c.mp3  disc 1  disc2  longer title2.mp3  longer title3.mp3  long title.mp3  the title.mp3

./a/disc 1:
title1.mp3  title2.mp3

./a/disc2:
title1.mp3  title2.mp3

./b:
c.mp3  title1.mp3  title2.mp3  title3.mp3

./c:
c-pony2.mp4  pony3.mp3  pony4.mp3  pony.mp3

Las expresiones regulares son un asunto complicado, y he cometido muchos errores al escribirlas, por lo que agradecería cualquier comentario sobre la falta de mérito de este. Sé que encontré bastantes pruebas de esto.


fuente
1

He creado un programa Java de línea de comandos que facilita el cambio de nombre de los archivos (y directorios), especialmente para las secuencias de comandos. Es gratuito y de código abierto, por lo que puede modificarlo al contenido de su corazón:

RenameWand
http://renamewand.sourceforge.net/

Algunos ejemplos de uso relevantes:

Mueva los archivos del formulario "<a> - <b>"a su directorio respectivo "<a>":

java -jar RenameWand.jar  "<a> - <b>"  "<a>/<b>"

Ordene los archivos por hora de última modificación y cámbieles el nombre con un número de 3 dígitos:

java -jar RenameWand.jar  "<a>"  "<3|#FT> <a>"

Reorganizar partes del nombre de archivo y cambiar mayúsculas y minúsculas:

java -jar RenameWand.jar  "<album> - <artist> - <song>.<ext>" 
                          "<artist.upper> <album.title> - <song>.<ext.lower>"
Zach Scrivena
fuente
1

zmv La herramienta de cambio de nombre zsh es muy buena.

# zmv "programmable rename"
# Replace spaces in filenames with a underline
zmv '* *' '$f:gs/ /_'
# Change the suffix from *.sh to *.pl
zmv -W '*.sh' '*.pl'
# lowercase/uppercase all files/directories
$ zmv '(*)' '${(L)1}' # lowercase
$ zmv '(*)' '${(U)1}' # uppercase

Más notas aquí ...

ocodo
fuente
0

Para los pingüinos, esto se hace fácilmente en un script de shell o un script AWK. Para nosotros, simples mortales, es posible que desee probar Midnight Commander. Está en la mayoría de las distribuciones de Linux, desde un indicador de comandos de tipo shell mc -a. Puede cambiar el nombre de los archivos con expresiones regulares. Usé el artículo en GeekStuff http://www.thegeekstuff.com/2009/06/how-to-rename-files-in-group/ para ayudarme.

TechScott
fuente
0

Aquí hay un ejemplo simple de línea de comandos. Tenía la palabra "blanco" en medio de los nombres de un montón de archivos png. Quería sacarlo y dejar solo un guión bajo. Esto hizo el truco:

for i in *.png; do mv "$i" "${i/white/}"; done
William Jockusch
fuente
0

Use vidir y luego use las funciones de su editor para aplicar el patrón de cambio de nombre.

NOMBRE

vidir - editar directorio

SINOPSIS

vidir [--verbose] [directorio | archivo | -] ...

DESCRIPCIÓN

Vidir permite editar el contenido de un directorio en un editor de texto. Si no se especifica ningún directorio, se edita el directorio actual.

Al editar un directorio, cada elemento del directorio aparecerá en su propia línea numerada. Estos números son cómo vidir realiza un seguimiento de los elementos que se cambian. Elimine líneas para eliminar archivos del directorio o edite nombres de archivo para cambiar el nombre de los archivos. También puede cambiar pares de números para intercambiar nombres de archivos.

Tenga en cuenta que si se especifica "-" como el directorio para editar, lee una lista de nombres de archivos de stdin y los muestra para su edición. Alternativamente, se puede especificar una lista de archivos en la línea de comando.

EJEMPLOS

vidir vidir * .jpeg Usos típicos.

encontrar | vidir - Edite también contenidos de subdirectorio. Para eliminar subdirectorios, elimine todos sus contenidos y el subdirectorio mismo en el editor.

encontrar -tipo f | vidir: edita todos los archivos del directorio y subdirectorios actuales.

AUTOR

Joey Hess 2006-2010

Modificaciones por Magnus Woldrich 2011

DERECHOS DE AUTOR

Copyright 2006-2011 los vidir "AUTOR" como se enumeran arriba.

Licenciado bajo la GNU GPL.

Peter Eisentraut
fuente
0

En un * nix sin perl renamedisponible

En algunos * nix no hay cambio de nombre disponible, por lo que es necesario cambiar el nombre utilizando algún otro método. Hace unos años sugerí zmvaquí que, aunque excelente, tampoco está necesariamente disponible.

Usando builtins y sed, podemos crear rápidamente un script de shell para hacer esto, lo que nos da una sintaxis muy similar al script de cambio de nombre de perl, mientras que carece de algo de manejo de errores, hace el trabajo.

sedrename() {
  if [ $# -gt 1 ]; then
    sed_pattern=$1
    shift
    for file in $(ls $@); do
      mv -v "$file" "$(sed $sed_pattern <<< $file)"
    done
  else
    echo "usage: $0 sed_pattern files..."
  fi
}

Uso

sedrename 's/Beethoven\ -\ //g' *.mp3

before:

./Beethoven - Fur Elise.mp3
./Beethoven - Moonlight Sonata.mp3
./Beethoven - Ode to Joy.mp3
./Beethoven - Rage Over the Lost Penny.mp3

after:

./Fur Elise.mp3
./Moonlight Sonata.mp3
./Ode to Joy.mp3
./Rage Over the Lost Penny.mp3

Digamos que también queríamos crear carpetas de destino ...

Como mvno crea carpetas que no podemos usar sedrenamecomo está aquí, pero es un cambio bastante pequeño, así que creo que sería bueno incluirlo también.

Necesitamos una función de utilidad abspath(o ruta absoluta) para poder generar la (s) carpeta (s) de destino para un patrón sed / rename que incluye una nueva estructura de carpetas.

abspath () { case "$1" in
               /*)printf "%s\n" "$1";;
               *)printf "%s\n" "$PWD/$1";;
             esac; }

Esto asegurará que sepamos los nombres de nuestras carpetas de destino. Cuando cambiemos el nombre, necesitaremos usarlo en el nombre del archivo de destino.

# generate the rename target
target="$(sed $sed_pattern <<< $file)"

# Use absolute path of the rename target to make target folder structure
mkdir -p "$(dirname $(abspath $target))"

# finally move the file to the target name/folders
mv -v "$file" "$target"

Aquí está el guión completo de la carpeta ...

sedrename() {
  if [ $# -gt 1 ]; then
    sed_pattern=$1
    shift
    for file in $(ls $@); do
      target="$(sed $sed_pattern <<< $file)"
      mkdir -p "$(dirname $(abspath $target))"
      mv -v "$file" "$target"
    done
  else
    echo "usage: $0 sed_pattern files..."
  fi
}

Por supuesto, todavía funciona cuando no tenemos carpetas específicas de destino también.

Si quisiéramos poner todas las canciones en una carpeta, ./Beethoven/podemos hacer esto:

Uso

sedrename 's|Beethoven - |Beethoven/|g' *.mp3

before:

./Beethoven - Fur Elise.mp3
./Beethoven - Moonlight Sonata.mp3
./Beethoven - Ode to Joy.mp3
./Beethoven - Rage Over the Lost Penny.mp3

after:

./Beethoven/Fur Elise.mp3
./Beethoven/Moonlight Sonata.mp3
./Beethoven/Ode to Joy.mp3
./Beethoven/Rage Over the Lost Penny.mp3

Ronda de bonificación ...

Usando este script para mover archivos de carpetas a una sola carpeta:

Suponiendo que deseamos reunir todos los archivos coincidentes y colocarlos en la carpeta actual, podemos hacerlo:

sedrename 's|.*/||' **/*.mp3

before:

./Beethoven/Fur Elise.mp3
./Beethoven/Moonlight Sonata.mp3
./Beethoven/Ode to Joy.mp3
./Beethoven/Rage Over the Lost Penny.mp3

after:

./Beethoven/ # (now empty)
./Fur Elise.mp3
./Moonlight Sonata.mp3
./Ode to Joy.mp3
./Rage Over the Lost Penny.mp3

Nota sobre patrones sed regex

Las reglas del patrón sed regular se aplican en este script, estos patrones no son PCRE (expresiones regulares compatibles con Perl). Podría haber extendido la sintaxis de expresión regular, utilizando cualquiera sed -ro sed -E dependiendo de su plataforma.

Consulte el POSIX compatible man re_formatpara obtener una descripción completa de los patrones de expresiones regulares básicas y extendidas de sed.

ocodo
fuente