Renomeando arquivos em lote

151

Eu tenho um diretório cheio de imagens:

image0001.png
image0002.png
image0003.png
...

E eu gostaria que uma única linha renomeiasse para (digamos).

0001.png
0002.png
0003.png
...

Como eu faço isso?

Homem da Internet
fonte
8
Esta é uma das principais perguntas frequentes sobre a linha de comando do Unix e não consigo encontrá-la neste site, então devemos criar este Wiki da comunidade?
Gilles
5
Eu não vejo o porquê. É uma pergunta específica com uma resposta verificável.
Internet man
3
Se você estiver executando o X, não será muito mais fácil do que thunar -B *.pngpara a ferramenta GUI de renomeação em massa do thunar.
dotjoe
@dotjoe Obrigado, Thunar é realmente interessante.
Volker Siegel

Respostas:

106

Se você estiver usando o Bash ou outro shell compatível com POSIX:

for f in *.png; do
    mv -- "$f" "${f#image}"
done
W_Whalley
fonte
2
Este é um dos métodos de substituição de parâmetros mostrados na Mendel Coopers Avançada guia Bash-scripting tldp.org/LDP/abs/html
W_Whalley
2
@W_Whalley Eu recomendo evitar esse guia, em favor do Guia Wooledge Bash .
Curinga
@Wildcard: quais são suas razões para recomendar evitar o guia ABS?
Christian Severin
@ChristianSeverin promoção de más práticas e códigos quebrados. Verifique os links na minha página de perfil.
Curinga
Se você não souber como adaptar este exemplo para diferentes padrões de arquivo, consulte a Seção de expansão de parâmetros do guia mencionado acima.
Lex82
108

No Debian e derivativos, o Perl renamefunciona da mesma forma sed:

  rename -v 's/image//' *.png

Há também a renamede util-linuxque funciona como este, em vez disso:

  rename image '' *.png
Homem da Internet
fonte
6
você realmente deve explicar que este é um programa perl que talvez precise ser instalado e que usa expressões regulares como argumento.
Ah, eu não estava ciente disso. Vou dar crédito para a resposta canônica, quando eu identificá-lo :)
homem Internet
5
Este renameprograma veio de uma distribuição de exemplos Perl. Debian e Ubuntu enviam como /usr/bin/rename. Outras variantes do Unix podem não fornecer, ou podem fornecer uma completamente diferente /usr/bin/rename.
Gilles
1
Algumas versões do renametake a de que padrão de substituição:rename [options] <expression> <replacement> <file>...
mescla
1
Se você estiver usando um sistema baseado no Debian, então sudo apt-get install rename, poderá usar o comando rename. É sed para nomes de arquivos.
Ctrl-alt-delor 31/12/16
41

zmv

O shell zsh possui um poderoso comando de renomeação de lote chamado zmv.

Primeiro, você precisa habilitar o zmvcomando da seguinte maneira (isso pode entrar no seu ~/.zshrc).

autoload zmv

A sintaxe básica é zmv PATTERN REPLACEMENT. O padrão é uma expressão glob shell. Partes do padrão podem estar entre parênteses. O texto de substituição pode conter $1, $2, etc, para se referir ao grupo parenthesised Nth no padrão. Por exemplo:

zmv 'image(*.png)' '$1'

Você também pode pedir zsh para definir automaticamente $1, $2, etc, para coincidir com os caracteres curinga no padrão:

zmv -w 'image*.png' '$1.png'
Gilles
fonte
4
sweeeeeeeeeeeeeeeeeet. ainda outra razão pela qual eu deveria estar aprendendo zsh.
Ixtmixilix 11/11/19
1
@ixtmixilix o que há para aprender? Comece a usá-lo e, talvez, adicione prezto ( github.com/sorin-ionescu/prezto ) para obter mais detalhes.
Gerry
Muito legal, como apontado no manual do zmv, isso pode ser ainda mais simplificado adicionando o pseudônimo mmv = 'noglob zmv -W' a: mmv * .c.orig orig / *. C
Bretsko
Permitindo zmvprezto requer descomentando a linha em seu ~ / .zpreztorc seguir # Set the Zsh functions to load (man zshcontrib).dandozstyle ':prezto:load' zfunction 'zargs' 'zmv'
33

Normalmente, uso o utilitário mmv ( página de manual ) agradável e simples para este caso de uso:

$ mmv "image*.png" "#1.png"

executará sua tarefa.

O #1padrão no destino será substituído pelo que corresponder ao curinga no padrão de origem. Isso também funciona para vários caracteres curinga e pode ser usado, por exemplo, para alterar a ordem das partes dos nomes de arquivos. Você também pode facilmente fazer coisas mais complicadas, como converter letras minúsculas em maiúsculas.

Certifique-se de proteger os padrões do shell, citando.

Marcel Stimberg
fonte
Obrigado por apontar este utilitário. Encontrei nos repositórios Debian, Ubuntu e Cygwin. Eu tive problemas com a página de manual, mas encontrei algumas páginas da Web e essa pergunta do Stack Overflow que ajudaram a explicar como você a estava usando. stackoverflow.com/questions/417916/how-to-do-a-mass-rename
W_Whalley
Obrigado, adicionei mais algumas informações à resposta para torná-la mais clara.
Marcel Stimberg
3
Não é possível vomitar o suficiente! É tão simples e amigável. Disponível para OS X em homebrew.
Greg Dubicki
9

POSIX sh para loop

Usa sed para renomear

for i in image*jpg
do 
  mv -v "$i" "$(echo "$i" | sed -e 's/^\.\/image//' - )"
done
X Tian
fonte
6

Eu gosto do Perl:

perl -nlE '$old=$_; s/image//; qx(mv $old $_)'

Você também pode usar o mesmo padrão para outras tarefas, como copiar os arquivos para outro diretório:

perl -nlE '$old=$_; s(image)(/path/to/new/dir/); qx(mv $old $_)'
gvkv
fonte
2
Ou (mais seguro!):rename($old,$_)
reinierpost
5

qmv

O comando qmvde renameutilsabre um editor mostrando uma lista de nomes de arquivos com duas colunas, separadas por uma guia. Cada linha mostra um dos nomes de arquivo, o mesmo nas duas colunas. A coluna da direita está representando os novos nomes dos arquivos.
Para fazer alterações, edite os nomes no lado direito. Neste exemplo, :%s/...ou o modo de bloqueio visual é útil.

Nomes de arquivos no seu editor

$ qmv *.png

No editor:

image0001.png           image0001.png
image0002.png           image0002.png
image0003.png           image0003.png         
~                                             
~                                             
~                                             
~                                             
"/tmp/user/1000/qmvxWyVMs" 3L, 93C

Edite nomes na coluna da direita:
(Removendo o imageprefixo de todas as linhas usando o modo de bloco visual)

image0001.png           0001.png
image0002.png           0002.png
image0003.png           0003.png         
~                                             
~                                             
~                                             
~                                             
:wq

Log de renomeação:

image0001.png -> 0001.png
image0002.png -> 0002.png
image0003.png -> 0003.png

(por exemplo Ubuntu: apt-get install renameutils)

Volker Siegel
fonte
3

recursivo

recursão fácil selecionando arquivos de imagem * png e não assume a necessidade de lidar com nova linha nos nomes de arquivo

find . -name "image*.png" | while read f; do mv -v "$f" "$(echo "$f" | sed -e 's/^\.\/image//' - )"; done

Seguro, pode lidar com espaços, novas linhas, barras invertidas e qualquer outra coisa :

find . -name "image*.png" | while IFS= read -r f; do 
   mv -v "$f" "$(echo "$f" | sed -e 's/^\.\/image//' - )"; 
done
X Tian
fonte
1

POSIX sh usando um loop while

Lendo nomes do findcomando.

find . -maxdepth 1 -type f -name 'image*png' | while IFS= read -r f; do
  mv -v "$f" "$(echo "$f" | sed -e 's/^\.\/image//' - )"
done

Lendo nomes de um arquivo

while IFS= read -r f; do mv -v "$f" "$(echo "$f"|sed -e 's/^\.\/image//' - )"; done < flist
X Tian
fonte
1

Para Windows e linux , esse script Perl funcionará; nesse caso:

$ rnm -l 's/^image//' '*.png'

O script pode ser executado recursivamente em diretórios e até mesmo acrescentando uma contagem a todos eles:

$ rnm -r 's/^/$counter./' '/\.png$/'

Os caracteres UTF-8 também são tratados corretamente, no Windows e no linux.

circulosmeos
fonte
0

Você pode usar esta ferramenta: rnm ( página da web )

Para o seu caso, o comando seria:

rnm -rs '/^image//' *.png

Você pode encontrar mais exemplos / documentos aqui .

Jahid
fonte
0

Tente brename ( https://github.com/shenwei356/brename ), uma ferramenta prática de linha de comando de plataforma cruzada para renomear arquivos / diretórios em lote com segurança por meio de expressão regular (compatível com Windows, Linux e OS X).

@patrickDurusau disse:

O Linux tem uma variedade de opções de renomeação de arquivos em lote, mas eu não vi nenhuma falha no nome que apareceu em mim.

Recursos:

  • Plataforma cruzada . Suporte para Windows, Mac OS X e Linux.
  • Seguro . Ao verificar possíveis conflitos e erros .
  • Filtragem de arquivos . Suporte para inclusão e exclusão de arquivos por meio de expressão regular. Não há necessidade de executar comandos como find ./ -name "*.html" -exec CMD.
  • Renomeando sub-correspondência com o valor correspondente por meio do arquivo de valores-chave .
  • Renomear via número crescente ascendente .
  • Renomear recursivamente arquivos e diretórios .
  • Suporte a funcionamento a seco .
  • Saída colorida .

Comando:

$ brename -f .png -p image
[INFO] checking: [ ok ] 'image0001.png' -> '0001.png'
[INFO] checking: [ ok ] 'image0002.png' -> '0002.png'
[INFO] checking: [ ok ] 'image0003.png' -> '0003.png'
[INFO] 3 path(s) to be renamed
[INFO] renamed: 'image0001.png' -> '0001.png'
[INFO] renamed: 'image0002.png' -> '0002.png'
[INFO] renamed: 'image0003.png' -> '0003.png'
[INFO] 3 path(s) renamed
Wei Shen
fonte
-5

ls * png | enquanto lê -rf; do f2 = "` echo $ f | sed -e's / imagem // '`"; mv $ f $ f2; feito

Ivan P
fonte
Algo não está certo: "mv: operando de arquivo de destino ausente após 'image0001.png'" "
Internet man
3
Existem muitos problemas com o seu código. Analisar a saída de lsestá apenas pedindo problemas. readdeveria ser read -r. todas as substituições de variáveis ​​devem estar entre aspas duplas.
Gilles
Você poderia escrever isso de forma mais eficaz como for f in *png; do f2="$(echo "$f" | sed -e 's/image//')"; mv "$f" "$f2"; done. A análise lsnão é necessária nem é uma boa ideia .
kojiro