Podemos asumir que sed
está disponible en cualquier * nix, pero no podemos estar seguros de que sea compatible sed -n
con la generación de comandos mv. ( NOTA: solo GNU sed
hace esto).
Aun así, bash incorporado y sed, podemos rápidamente crear 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:
Dado mv
que no crea carpetas de destino automáticamente, no podemos usar nuestra versión inicial de sedrename
.
Es un cambio bastante pequeño, por lo que sería bueno incluir esa función:
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 lo tengamos, podemos generar la (s) carpeta (s) de destino para un patrón sed / renombrar que incluye una nueva estructura de carpetas.
Esto asegurará que sepamos 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á el script completo con reconocimiento de carpetas ...
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, también funciona cuando no tenemos carpetas de destino específicas.
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 quisiéramos recopilar 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 expresiones regulares sed
En este script se aplican reglas de patrones sed regulares, estos patrones no son PCRE (Expresiones regulares compatibles con Perl). Podría tener la sintaxis de expresión regular extendida sed, usando sed -r
o sed -E
dependiendo de su plataforma.
Consulte la compatibilidad con POSIX man re_format
para obtener una descripción completa de los patrones de expresiones regulares básicas y extendidas de sed.