Em um * nix sem perl rename
disponível
Em alguns * nix, não há renomeação disponível; portanto, é necessário fazer a renomeação usando outro método. Alguns anos atrás, sugeri zmv
aqui que, embora ótimo, também não está necessariamente disponível.
Usando builtins e sed, podemos rapidamente criar um script de shell para fazer isso, o que nos dá uma sintaxe muito semelhante ao script de renomeação do perl, enquanto falta alguma gentileza no tratamento de erros, ele faz o trabalho.
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 também desejássemos criar pastas de destino ...
Como mv
não cria pastas que não podemos usar sedrename
como está aqui, mas é uma mudança bastante pequena, então acho que seria bom incluí-la também.
Precisamos de uma função de utilitário abspath
(ou caminho absoluto) para podermos gerar a (s) pasta (s) de destino para um padrão sed / renomear que inclua nova estrutura de pastas.
abspath () { case "$1" in
/*)printf "%s\n" "$1";;
*)printf "%s\n" "$PWD/$1";;
esac; }
Isso garantirá que sabemos os nomes de nossas pastas de destino. Quando renomeamos, precisamos usá-lo no nome do arquivo 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"
Aqui está o script ciente da pasta completa ...
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
}
Obviamente, ele ainda funciona quando não temos pastas de destino específicas também.
Se quisermos colocar todas as músicas em uma pasta, ./Beethoven/
podemos fazer o seguinte:
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
Rodada de bônus ...
Usando este script para mover arquivos de pastas para uma única pasta:
Supondo que desejássemos reunir todos os arquivos correspondentes e colocá-los na pasta atual, podemos fazê-lo:
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 padrões de regex sed
As regras regulares de padrões sed aplicam-se neste script, esses padrões não são PCRE (expressões regulares compatíveis com Perl). Você pode ter usado a sintaxe da expressão regular estendida, usando sed -r
ou sed -E
dependendo da sua plataforma.
Consulte o compatível com POSIX man re_format
para obter uma descrição completa dos padrões de regexp básicos e avançados sed.