Renomear em massa, alterar prefixo

53

Como posso substituir em massa o prefixo de muitos arquivos?

Eu tenho muitos arquivos como

  • TestSRConnectionContext.h
  • TestSRConnectionContext.m

Eu gostaria de mudar todos eles para

  • CLConnectionContext.h
  • CLConnectionContext.m

Como eu faria isso?

ErikTJ
fonte

Respostas:

38
for name in TestSR*
do
    newname=CL"$(echo "$name" | cut -c7-)"
    mv "$name" "$newname"
done

Isso usa a substituição do comando bash para remover os 6 primeiros caracteres do nome do arquivo de entrada via cut, precede CLo resultado e armazena-o $newname. Em seguida, renomeia o nome antigo para o novo nome. Isso é realizado em todos os arquivos.

cut -c7-especifica que somente caracteres após o índice 7 devem ser retornados da entrada. 7-é um intervalo que começa no índice 7 sem fim; isto é, até o final da linha.

Anteriormente, eu tinha usado cut -b7-, mas -cdeveria ser usado para lidar com codificações de caracteres que poderiam ter vários bytes por caractere, como UTF-8.

mrb
fonte
Thx, eu também tenho isso agora. Marcando como resposta. Thx
ErikTJ
Isso funciona muito bem, obrigado. Você pode explicar o que o -b7- faz? Esta é uma referência à lista de bytes? ss64.com/bash/cut.html
imjared 26/09/13
@imjared Atualizou a resposta com mais detalhes.
Mrb 26/09/2013
56

Eu diria que o mais simples é usar apenas o renamecomando que é comum em muitas distribuições Linux. Existem duas versões comuns desse comando, portanto, verifique sua página de manual para descobrir qual você possui:

## rename from Perl (common in Debian systems -- Ubuntu, Mint, ...)
rename 's/^TestSR/CL/' *

## rename from util-linux-ng (common in Fedora systems, Red Hat, CentOS, ...)
rename TestSR CL *

Se você quiser usar a versão do util-linux-ng em um sistema Debian, ela estará disponível sob o nome rename.ul

carandraug
fonte
7
Uma ressalva: várias versões do renameexistem na natureza. Verifique a renamedocumentação local para descobrir como usar a sua.
Jw013 # 6/12
Para remover o alias dorename TestSR '' *
Bsienn
hmm ... rename "\<pre\>" "" *->Unterminated <> operator at (user-supplied code).
Flash Thunder
32

A expansão dos parâmetros do shell é suficiente para transformações simples como essa. A substituição de comandos é menos eficiente devido à necessidade de gerar processos extras (para a própria substituição de comandos e o cut/ sed).

for f in TestSR*; do mv "$f" "CL${f#TestSR}"; done
jw013
fonte
Explicação: TestSR*localiza os arquivos, CL${f#TestSR}será o novo nome. O material após o #será substituído pelo nome do arquivo ( f).
Joe Eifert
4

Aqui está uma maneira:

ls *.{h,m} | while read a; do n=CL$(echo $a | sed -e 's/^Test//'); mv $a $n; done
  • ls *.{h,m} -> Encontre todos os arquivos com extensão .h ou .m
  • n=CL -> Adicione um prefixo CL ao nome do arquivo
  • sed -e 's/^Test//' -> Remove o prefixo Teste do nome do arquivo
  • mv $a $n -> Executa a renomeação
Eric
fonte
3

Você pode tentar com:

for i in TestSR*; do mv ${i} ${i/#TestSR/CL}; done

Consulte man bash(seção "Expansão de parâmetros") para detalhes.

Francesco Turco
fonte
1

Bem, não foi tão difícil quanto eu pensava.

$ for f in TestSR*.m; do mv $f CL$(echo $f | cut -c7-); done;
$ for f in TestSR*.h; do mv $f CL$(echo $f | cut -c7-); done;
ErikTJ
fonte
11
Caso isso ajude no futuro, você não precisará repetir os comandos para seus dois padrões; você pode usar (por exemplo): for f in TestSR*.[mh], for f in TestSR*.{m,h}, for f in TestSR*.m TestSR*.h.
Mrb 6/09/12
1

Se você precisar de algo mais pernicioso, pode fazer isso

perl -e 'for(@ARGV) { rename($_, $n) if( ($n = $_ ) =~ s/^TestSR/CL/) }' *
user1146332
fonte