varios renombrar recursivamente nombre masivo consola cambiar archivos archivo bash shell file-rename

bash - recursivamente - renombrar archivos linux masivo



Lotes de cambio de nombre de archivos con Bash (9)

Aquí hay un POSIX casi equivalente a la respuesta actualmente aceptada . Esto intercambia la expansión de parámetros Bash-only ${variable/substring/replacement} por uno que está disponible en cualquier shell compatible con Bourne.

for i in ./*.pkg; do mv "$i" "${i%-[0-9.]*.pkg}.pkg" done

La expansión de parámetro ${variable%pattern} produce el valor de variable con cualquier sufijo que coincida con el pattern eliminado. (También hay ${variable#pattern} para eliminar un prefijo).

Mantuve el subpatrón -[0-9.]* De la respuesta aceptada aunque tal vez sea engañoso. No es una expresión regular, sino un patrón glob; por lo que no significa "un guión seguido de cero o más números o puntos". En cambio, significa "un guion, seguido de un número o un punto, seguido de cualquier cosa". El "cualquier cosa" será la coincidencia más corta posible, no la más larga. (Bash ofrece ## y %% para recortar el prefijo o sufijo más largo posible, en lugar del más corto).

¿Cómo puede Bash cambiar el nombre de una serie de paquetes para eliminar sus números de versión? He estado jugando con expr y %% , sin éxito.

Ejemplos:

Xft2-2.1.13.pkg convierte en Xft2.pkg

jasper-1.900.1.pkg convierte en jasper.pkg

xorg-libXrandr-1.2.3.pkg convierte en xorg-libXrandr.pkg


Esto parece funcionar suponiendo que

  • todo termina con $ pkg
  • sus versiones # siempre comienzan con un "-"

quita el .pkg, luego quítatelo ...

for x in $(ls); do echo $x $(echo $x | sed ''s//.pkg//g'' | sed ''s/-.*//g'').pkg; done


Gracias por estas respuestas. También tuve algún tipo de problema. Mover archivos .nzb.queued a archivos .nzb. Tenía espacios y otros cruces en los nombres de archivo y esto resolvió mi problema:

find . -type f -name "*.nzb.queued" | sed -ne "s/^/(/(.*/).nzb.queued/)$/mv -v /"/1/" /"/2.nzb/"/p" | sh

Se basa en la respuesta de Diomidis Spinellis.

La expresión regular crea un grupo para el nombre de archivo completo, y un grupo para la parte anterior .nzb.queued y luego crea un comando de movimiento de shell. Con las cuerdas citadas. Esto también evita crear un bucle en el script de shell porque esto ya lo hace sed.


Haré algo como esto:

for file in *.pkg ; do mv $file $(echo $file | rev | cut -f2- -d- | rev).pkg done

supuso que todos sus archivos están en el directorio actual. Si no es así, intente utilizar Find como se indicó anteriormente por Javier.

EDITAR : Además, esta versión no usa ninguna característica específica de bash, como las anteriores, lo que te lleva a una mayor portabilidad.


Podemos suponer que sed está disponible en cualquier * nix, pero no podemos estar seguros de que admita sed -n para generar comandos mv. ( NOTA: solo GNU sed hace esto).

Aun así, bash builtins y sed, podemos acelerar rápidamente una función de shell para hacer esto.

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|/(.*/)/(-[0-9.]*/.pkg/)|/1/2|'' *.pkg before: ./Xft2-2.1.13.pkg ./jasper-1.900.1.pkg ./xorg-libXrandr-1.2.3.pkg after: ./Xft2.pkg ./jasper.pkg ./xorg-libXrandr.pkg

Crear carpetas de destino:

Como mv no crea automáticamente carpetas de destino, no podemos usar nuestra versión inicial de sedrename .

Es un cambio bastante pequeño, por lo que sería bueno incluir esa característica:

Necesitaremos una función de utilidad, abspath (o ruta absoluta) ya que bash no tiene esta compilación.

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

Una vez que tenemos eso, podemos generar la (s) carpeta (s) de destino para un patrón sed / rename que incluye una nueva estructura de carpeta.

Esto asegurará que conocemos los nombres de nuestras carpetas de destino. Cuando cambiemos el nombre, tendremos que 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á la secuencia de comandos completa 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.

Si queríamos 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 esta secuencia de comandos para mover archivos de carpetas a una sola carpeta:

Suponiendo que quisiéramos 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 los patrones de sedgexpress

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

Ver el man re_format conformes con POSIX man re_format para una descripción completa de los patrones de man re_format básicas y extendidas.


Podría usar la función de expansión de parámetros de bash

for i in ./*.pkg ; do mv "$i" "${i/-[0-9.]*.pkg/.pkg}" ; done

Se necesitan presupuestos para nombres de archivos con espacios.


Si todos los archivos están en el mismo directorio, la secuencia

ls | sed -n ''s//(.*/)/(-[0-9.]*/.pkg/)/mv "/1/2" "/1.pkg"/p'' | sh

hará tu trabajo El comando sed creará una secuencia de comandos mv , que luego puede conectar al shell. Lo mejor es ejecutar primero la tubería sin el seguimiento | sh | sh para verificar que el comando hace lo que quiere.

Para recurse a través de directorios múltiples, use algo como

find . -type f | sed -n ''s//(.*/)/(-[0-9.]*/.pkg/)/mv "/1/2" "/1.pkg"/p'' | sh

Tenga en cuenta que en sed, la secuencia de agrupación de expresiones regulares es corchetes precedidos por una barra invertida, /( y /) , en lugar de corchetes individuales ( y ) .


Tenía varios archivos *.txt para renombrarlos como .sql en la misma carpeta. a continuación funcionó para mí:

for i in /`ls *.txt | awk -F "." ''{print $1}''/` ;do mv $i.txt $i.sql; done


mejor uso sed para esto, algo así como:

find . -type f -name "*.pkg" | sed -e ''s/((.*)-[0-9.]*/.pkg)//1 /2.pkg/g'' | while read nameA nameB; do mv $nameA $nameB; done

descifrar la expresión regular se deja como un ejercicio (como se trata de nombres de archivos que incluyen espacios)