Podemos presumir que sed
está disponível em qualquer * nix, mas não podemos ter certeza de que suportará sed -n
a geração de comandos mv. ( NOTA: Apenas GNU sed
faz isso.)
Mesmo assim, bash builtins e sed, podemos rapidamente criar uma função shell para fazer isso.
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
Criação de pastas de destino:
Uma vez mv
que não cria pastas de destino automaticamente, não podemos usar nossa versão inicial do sedrename
.
É uma mudança bastante pequena, então seria bom incluir esse recurso:
Precisaremos de uma função de utilidade abspath
(ou caminho absoluto) já que o bash não tem essa função.
abspath () { case "$1" in
/*)printf "%s\n" "$1";;
*)printf "%s\n" "$PWD/$1";;
esac; }
Assim que tivermos isso, podemos gerar a (s) pasta (s) de destino para um padrão sed / rename que inclui uma nova estrutura de pastas.
Isso garantirá que saibamos os nomes de nossas pastas de destino. Quando renomearmos, precisaremos 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 com reconhecimento de pasta completo ...
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
}
Claro, 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 desejamos reunir todos os arquivos correspondentes e colocá-los na pasta atual, podemos fazer isso:
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
Regras regulares de padrão sed se aplicam a este script, esses padrões não são PCRE (Expressões regulares compatíveis com Perl). Você poderia ter estendido a sintaxe de expressão regular do sed, usando sed -r
ou sed -E
dependendo da sua plataforma.
Consulte o POSIX compatível man re_format
para uma descrição completa dos padrões de expressão regular básica e estendida sed.