Renomeação em massa, * versão nix

11

Eu estava procurando uma maneira de renomear um grande número de arquivos com nomes semelhantes, assim como este (uma questão relacionada ao Windows), exceto pelo fato de estar usando o * nix (Ubuntu e FreeBSD, separadamente). Para resumir, enquanto uso o shell (Bash, CSH etc.), como renomeio em massa vários arquivos, como, por exemplo, os seguintes arquivos:

Beethoven - Fur Elise.mp3
Beethoven - Sonata ao luar.mp3
Beethoven - Ode à Joy.mp3
Beethoven - Raiva pela perda de um centavo.mp3

será renomeado como estes?

Fur Elise.mp3
Moonlight Sonata.mp3
Ode à Joy.mp3
Raiva sobre a moeda 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 essas informações no nome do arquivo será redundante.

Paolo B.
fonte

Respostas:

12

O utilitário de renomeação fará o que você deseja.

Apenas use rename 's/Beethoven\ -\ //g' *.mp3


fonte
Você pode editar para fornecer um link para o utilitário, ou é padrão nas duas distribuições mencionadas (Ubuntu e FreeBSD)?
21119 Chris W. Rea
1
Vem com Perl. O Debian o usa como comando de renomeação, então eu suspeito que o Ubuntu também. Há outro comando 'renomear' que não vale nada, portanto verifique a página do manual.
Derobert 23/08/09
uau, a sintaxe de renomeação é muito parecida com vim replace: D
nXqd
a porta em / usr / ports / sysutils / renomeação funcionou perfeitamente no FreeBSD
Josh W.
10

Como muitas coisas no 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

Observe que a ferramenta de renomeação no Fedora 10 não é o mesmo programa e funciona de maneira diferente. Faz parte de um pacote diferente, util-linux-ng, e pode ser encontrado aqui .

Costumo ir ao shell em busca de um hábito (depois de todas essas ferramentas nem sempre existirem).

mkdir -p Beethoven
for x in Beethoven\ -\ *
do
mv "$x" Beethoven/"${x/Beethoven - /}"
done

Isso criará o diretório Beethoven e, em seguida, mova o arquivo para esse 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 de:

$ ls Beethoven/
Fur Elise.mp3                 Ode to Joy.mp3
Moonlight Sonata.mp3          Rage Over the Lost Penny.mp3
jtimberman
fonte
4

Experimente esta solução, implementada usando uma combinação de grep e renomear. Isso pressupõe que você tenha vários diretórios que precisam renomear. Se houver apenas alguns, eu adotaria a abordagem manual, com o padrão "Artista -" 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 da localização :
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. Observe que dentro de -exec , {} refere-se ao argumento transmitido por find (caminho do arquivo + nome). Os \;garante a ;é passado para mudar o nome e, em vez de indicar o fim da descoberta de comando.

O comando fornecido acima possui a opção -n (sem ação); portanto, ele só 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 ficar satisfeito com os resultados propostos.

Agora para o regexp.

  • ^ corresponde ao início da string.
  • $ corresponde ao final da sequência.
  • . corresponde a qualquer caractere.
  • *significa zero ou mais da construção anterior. por exemplo, .*significa zero ou mais caracteres.
  • \s significa qualquer caractere de espaço.
  • \S significa qualquer caractere não espacial.
  • Nada dentro ()é capturado e reflecte-se como $1, $2de acordo com a sua posição.

O regexp:

  • Procura uma estrutura de diretórios opcional no início, captura isso em $ 1: (.*/)
  • Ignora tudo até o " -":.*-
  • Captura o restante da string, exceto os espaços à esquerda e à direita, em US $ 2: (.*)
  • Reescreve o arquivo como $ 1 $ 2, que deve ser "/path/to/file/""filename.mp3"

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

Os negócios da Regexp são complicados e eu cometi muitos erros ao escrevê-los, por isso gostaria de receber qualquer opinião sobre a falta de mérito deste. Eu sei que encontrei alguns testando isso.

Nagul
fonte
1

Eu montei um programa Java de linha de comando que facilita a renomeação de arquivos (e diretórios), especialmente para scripts. É gratuito e de código aberto, para que você possa modificá-lo para o conteúdo do seu coração:

RenameWand
http://renamewand.sourceforge.net/

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 3 dígitos:

java -jar RenameWand.jar  "<a>"  "<3|#FT> <a>"

Reorganize partes do nome do arquivo e altere maiúsculas e minúsculas:

java -jar RenameWand.jar  "<album> - <artist> - <song>.<ext>" 
                          "<artist.upper> <album.title> - <song>.<ext.lower>"
Zach Scrivena
fonte
1

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

Mais notas aqui ...

ocodo
fonte
0

Para as cabeças do Penguin, isso é feito facilmente em um shell script ou AWK. Para nós, meros mortais, você pode tentar o Midnight Commander. Está na maioria das distribuições Linux, a partir de um prompt do shell, digite mc -a. Você pode renomear arquivos usando expressões regulares. Usei o artigo em GeekStuff http://www.thegeekstuff.com/2009/06/how-to-rename-files-in-group/ para me ajudar.

TechScott
fonte
0

Aqui está um exemplo simples da linha de comando. Eu tinha a palavra "branco" no meio dos nomes de um monte de arquivos png. Eu queria retirá-lo e deixar apenas um único sublinhado. Isso fez o truque:

for i in *.png; do mv "$i" "${i/white/}"; done
William Jockusch
fonte
0

Use o vidir e, em seguida, use os recursos do editor para aplicar o padrão de renomeação.

NOME

vidir - editar diretório

SINOPSE

vidir [--verbose] [diretório | arquivo | -] ...

DESCRIÇÃO

O vidir permite editar o conteúdo de um diretório em um editor de texto. Se nenhum diretório for especificado, o diretório atual será editado.

Ao editar um diretório, cada item do diretório aparecerá em sua própria linha numerada. Esses números são como o vidir controla quais itens são alterados. Exclua linhas para remover arquivos do diretório ou edite nomes de arquivos para renomear arquivos. Você também pode alternar pares de números para trocar nomes de arquivos.

Observe que se "-" for especificado como o diretório a ser editado, ele lerá uma lista de nomes de arquivos do stdin e exibirá aqueles para edição. Como alternativa, uma lista de arquivos pode ser especificada na linha de comando.

EXEMPLOS

vidir vidir * .jpeg Usos típicos.

encontrar | vidir - Edite também o conteúdo do subdiretório. Para excluir subdiretórios, exclua todo o seu conteúdo e o próprio subdiretório no editor.

encontre o tipo f | vidir - Edite todos os arquivos no diretório e subdiretórios atuais.

AUTOR

Joey Hess 2006-2010

Modificações por Magnus Woldrich 2011

DIREITO AUTORAL

Copyright 2006-2011 o vidir "AUTHOR" s como listado acima.

Licenciado sob a GNU GPL.

Peter Eisentraut
fonte
0

Em um * nix sem perl renamedisponí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 zmvaqui 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 mvnão cria pastas que não podemos usar sedrenamecomo 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 -rou sed -E dependendo da sua plataforma.

Consulte o compatível com POSIX man re_formatpara obter uma descrição completa dos padrões de regexp básicos e avançados sed.

ocodo
fonte