O utilitário de renomeação fará o que você quiser.
Use apenas rename 's/Beethoven\ -\ //g' *.mp3
Eu estava procurando uma maneira de renomear um grande número de arquivos com nomes semelhantes, muito parecido com este (uma questão relacionada ao Windows) , exceto que eu estou usando * nix (Ubuntu e FreeBSD, separadamente). Apenas para resumir, ao usar o shell (Bash, CSH, etc.) como renomear em massa um número de arquivos como, por exemplo, os seguintes arquivos:
Beethoven - Fur Elise.mp3
Beethoven - Sonata ao luar.mp3
Beethoven - Ode à Alegria.mp3
Beethoven - Raiva Sobre a Penny Perdida.mp3
será renomeado como este?
Fur Elise.mp3
Sonata do luar.mp3
Ode à Alegria.mp3
Raiva Sobre a Penny Perdida.mp3
A razão pela qual eu quero fazer isso é que essa coleção de arquivos irá para um diretório chamado "Beethoven" (ou seja, o prefixo dos nomes dos arquivos), e ter essa informação no próprio nome do arquivo será redundante.
O utilitário de renomeação fará o que você quiser.
Use apenas rename 's/Beethoven\ -\ //g' *.mp3
Como muitas coisas com o Linux / Unix, há mais de uma maneira de fazer isso!
Alguns podem usar mmv (massa mv).
O comando rename, ou prename que vem com alguns pacotes Perl (Ubuntu e Debian mais recentes) também pode fazer isso.
prename 's/Beethoven\ -\ //g' Beethoven*.mp3
Note que a ferramenta de renomeação no Fedora 10 não é o mesmo programa e funciona de maneira diferente. É parte de um pacote diferente, util-linux-ng e pode ser encontrado aqui .
Eu costumo ir ao shell fora do hábito (afinal de contas, tais ferramentas nem sempre existiam).
mkdir -p Beethoven
for x in Beethoven\ -\ *
do
mv "$x" Beethoven/"${x/Beethoven - /}"
done
Isto irá criar o diretório Beethoven, então mova o arquivo para o diretório / nome do arquivo, onde o nome do arquivo tem o "Beethoven -" substituído por nada.
Como teste, antes:
$ ls
Beethoven - Fur Elise.mp3 Beethoven - Ode to Joy.mp3
Beethoven - Moonlight Sonata.mp3 Beethoven - Rage Over the Lost Penny.mp3
Depois:
$ ls Beethoven/
Fur Elise.mp3 Ode to Joy.mp3
Moonlight Sonata.mp3 Rage Over the Lost Penny.mp3
Experimente esta solução, implementada usando uma combinação de grep e rename. Isto está assumindo que você tem um monte de diretórios que você precisa renomear. Se houver apenas alguns, eu usaria a abordagem manual, com o padrão "Artist -" codificado para cada um.
# Rename any mp3 files in the directory hierarchy of type "a - b.mp3" to "b.mp3"
find . -name "*.mp3" -exec rename -n -v 's|^(.*/).*-\s*(.*)\s*$|$1$2|g' {} \;
Explicação de encontrar :
O comando find localiza todos os arquivos com extensão .mp3 na hierarquia de arquivos atual e chama o argumento passado para -exec para cada um. Note que dentro de -exec , {} refere-se ao argumento passado por find (caminho do arquivo + nome). O \;
garante que ;
seja passado para renomear e, em vez de indicar o fim do comando localizar .
O comando dado acima tem o interruptor -n (sem ação); por isso, só lhe dirá o que aconteceria se você o executasse. Eu recomendo que você execute este comando sem a opção -n somente depois de executá-lo uma vez e estar satisfeito com os resultados propostos.
Agora para o regexp.
^
corresponde ao início da cadeia. $
corresponde ao final da string. .
corresponde a qualquer caractere. *
significa zero ou mais da construção precedente. por exemplo, .*
significa zero ou mais caracteres. \s
significa qualquer caractere de espaço. \S
significa qualquer caractere não espacial. ()
é capturada e é refletida como $1
, $2
, dependendo de sua posição. O regexp:
(.*/)
-
": .*-
(.*)
Aqui está o meu teste:
/tmp/test$ ls -R
.:
a b c z-unknown.mp3
./a:
a3.mp3 a - longer title3.mp3 c.mp3 disc2
a - longer title2.mp3 a - long title.mp3 disc 1 the band - the title.mp3
./a/disc 1:
a - title1.mp3 a - title2.mp3
./a/disc2:
a - title1.mp3 a - title2.mp3
./b:
cd - ab - title3.mp3 cd - title1.mp3 cd - title2.mp3 c.mp3
./c:
c-pony2.mp4 c - pony3.mp3 c - pony4.mp3 c-pony.mp3
/tmp/test$ find . -name "*.mp3" -exec rename -v 's|^(.*/).*-\s*(.*)\s*$|$1$2|g' {} \;
./c/c-pony.mp3 renamed as ./c/pony.mp3
./c/c - pony4.mp3 renamed as ./c/pony4.mp3
./c/c - pony3.mp3 renamed as ./c/pony3.mp3
./z-unknown.mp3 renamed as ./unknown.mp3
./a/the band - the title.mp3 renamed as ./a/the title.mp3
./a/a - longer title2.mp3 renamed as ./a/longer title2.mp3
./a/a - longer title3.mp3 renamed as ./a/longer title3.mp3
./a/disc 1/a - title1.mp3 renamed as ./a/disc 1/title1.mp3
./a/disc 1/a - title2.mp3 renamed as ./a/disc 1/title2.mp3
./a/a - long title.mp3 renamed as ./a/long title.mp3
./a/disc2/a - title1.mp3 renamed as ./a/disc2/title1.mp3
./a/disc2/a - title2.mp3 renamed as ./a/disc2/title2.mp3
./b/cd - title1.mp3 renamed as ./b/title1.mp3
./b/cd - title2.mp3 renamed as ./b/title2.mp3
./b/cd - ab - title3.mp3 renamed as ./b/title3.mp3
/tmp/test$ ls -R
.:
a b c unknown.mp3
./a:
a3.mp3 c.mp3 disc 1 disc2 longer title2.mp3 longer title3.mp3 long title.mp3 the title.mp3
./a/disc 1:
title1.mp3 title2.mp3
./a/disc2:
title1.mp3 title2.mp3
./b:
c.mp3 title1.mp3 title2.mp3 title3.mp3
./c:
c-pony2.mp4 pony3.mp3 pony4.mp3 pony.mp3
O Regexp é um negócio complicado, e cometi muitos erros ao escrevê-los, por isso gostaria de receber qualquer informação sobre a falta de mérito deste. Eu sei que encontrei alguns testes.
Eu criei um programa Java de linha de comando que torna a renomeação de arquivos (e diretórios) muito fácil, especialmente para scripts. É grátis e de código aberto, para que você possa modificá-lo para o conteúdo do seu coração:
RenameWand link
Alguns exemplos de uso relevantes:
Mova os arquivos do formulário "<a> - <b>"
para o respectivo diretório "<a>"
:
java -jar RenameWand.jar "<a> - <b>" "<a>/<b>"
Classifique os arquivos pela hora da última modificação e renomeie-os com um número de três dígitos:
java -jar RenameWand.jar "<a>" "<3|#FT> <a>"
Reorganize partes do nome do arquivo e altere o caso:
java -jar RenameWand.jar "<album> - <artist> - <song>.<ext>"
"<artist.upper> <album.title> - <song>.<ext.lower>"
zmv
A ferramenta de renomeação do zsh é muito boa.
# zmv "programmable rename"
# Replace spaces in filenames with a underline
zmv '* *' '$f:gs/ /_'
# Change the suffix from *.sh to *.pl
zmv -W '*.sh' '*.pl'
# lowercase/uppercase all files/directories
$ zmv '(*)' '${(L)1}' # lowercase
$ zmv '(*)' '${(U)1}' # uppercase
Para os pinguins, isso é feito facilmente em um shell script ou script AWK. Para nós, meros mortais, você pode querer experimentar o Midnight Commander. Está na maioria das distribuições linux, a partir de um prompt de shell tipo mc -a. Você pode renomear arquivos usando expressões regulares. Eu usei o artigo no GeekStuff link para me ajudar.
Aqui está um exemplo simples de linha de comando. Eu tinha a palavra "branco" no meio dos nomes de um monte de arquivos png. Eu queria tirá-lo e deixar apenas um único sublinhado. Isso fez o truque:
for i in *.png; do mv "$i" "${i/white/}"; done
Use vidir e use os recursos do editor para aplicar o padrão de renomeação.
NAME
vidir - edit directory
SYNOPSIS
vidir [--verbose] [directory|file|-] ...
DESCRIPTION
vidir allows editing of the contents of a directory in a text editor. If no directory is specified, the current directory is edited.
When editing a directory, each item in the directory will appear on its own numbered line. These numbers are how vidir keeps track of what items are changed. Delete lines to remove files from the directory, or edit filenames to rename files. You can also switch pairs of numbers to swap filenames.
Note that if "-" is specified as the directory to edit, it reads a list of filenames from stdin and displays those for editing. Alternatively, a list of files can be specified on the command line.
EXAMPLES
vidir vidir *.jpeg Typical uses.
find | vidir - Edit subdirectory contents too. To delete subdirectories, delete all their contents and the subdirectory itself in the editor.
find -type f | vidir - Edit all files under the current directory and subdirectories.
AUTHOR
Joey Hess 2006-2010
Modifications by Magnus Woldrich 2011
COPYRIGHT
Copyright 2006-2011 the vidir "AUTHOR"s as listed above.
Licensed under the GNU GPL.
rename
available Em alguns * nix não há renomeação disponível, então é necessário fazer o
renomeie usando algum outro método. Alguns anos atrás eu sugeri zmv
que, embora excelente, não está necessariamente disponível também.
Usando builtins e sed, podemos rapidamente agitar um script de shell para fazer isso nos dá uma sintaxe muito semelhante ao script perl rename, enquanto falta algum erro de manuseio, 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
}
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
Como mv
não cria pastas, não podemos usar sedrename
como é
aqui, mas é uma pequena mudança, então eu acho que seria legal
inclua também.
Precisamos de uma função de utilidade, abspath
(ou caminho absoluto) para que possamos
gerar a (s) pasta (s) de destino para um padrão sed / rename 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 das nossas pastas de destino. Quando nós renomear vamos precisar 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"
Este é o script ciente de 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
}
Claro, ainda funciona quando não temos pastas de destino específicas também.
Se quiséssemos colocar todas as músicas em uma pasta, ./Beethoven/
, podemos fazer isso:
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
Usando este script para mover arquivos de pastas para uma única pasta:
Supondo que queríamos 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
As regras regulares do padrão sed são aplicadas neste script, esses padrões não são
PCRE (expressões regulares compatíveis com Perl). Você poderia ter sed
sintaxe de expressão regular estendida, usando sed -r
ou sed -E
dependendo da sua plataforma.
Veja o man re_format
compatível com POSIX para obter uma descrição completa de
sed padrões básicos e estendidos de regexp.