En un * nix sin perl rename
disponible
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í zmv
aquí 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 mv
no crea carpetas que no podemos usar sedrename
como 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 -r
o sed -E
dependiendo de su plataforma.
Consulte el POSIX compatible man re_format
para obtener una descripción completa de los patrones de expresiones regulares básicas y extendidas de sed.