Como criar um script ou uma linha de comando que incrementa a parte variável do nome dos meus arquivos, mas alguns deles?

0

Eu tenho vários arquivos cujos nomes não estão corretos:

$ ls
devoirNote1_1_2.R  devoirNote1_1_5.R  devoirNote1_4_1.R
devoirNote1_1_3.R  devoirNote1_1.R    devoirNote1.R
devoirNote1_1_4.R  devoirNote1_2_1.R  example140.R

Eu quero alterar todos os devoirNote1_i_j.R com os inteiros i e j, exceto devoirNote1_4_1.R to devoirNote1_{i+1}_j.R (somente devoirNote1_4_1.R é deixado inalterado).

Pensei em usar o comando mv like mv devoirNote1_*_2.R devoirNote1_2_2.R , mas quando vários arquivos correspondem (por exemplo, se devoirNote1_1_2.R e devoirNote1_3_2.R estiverem presentes), isso cria um problema.

Portanto, como criar um script ou uma linha de comando que renomeie meus arquivos, incrementando uma das variáveis nos nomes de arquivos, mas não todos eles?

    
por ThePassenger 25.03.2017 / 16:31

3 respostas

0

A rename utility do Perl (*) pode ser usada para isso. Aplica um determinado comando Perl a cada nome de arquivo e renomeia o arquivo para qualquer um dos comandos para os quais o nome foi alterado.

Então, isso mudaria _1_ para _2_ em todos os arquivos que o glob corresponde.

rename 's/_1_/_2_/' devoirNote1_*_2.R

Incrementar numericamente pode ser feito com o /e modificado para o comando de substituição, tornando a peça de substituição um trecho Perl em vez de um literal.

rename -v 's/_(\d+)_/"_" . ($1 + 1) . "_"/e' devoirNote1_*_2.R

Isso selecionaria uma parte do nome do arquivo com dígitos entre os sublinhados, capturando os dígitos para $1 e substituindo-os pelo número aumentado um, com os sublinhados adicionados de volta. -v para o modo detalhado. Com a lista de arquivos em seu exemplo, isso imprimiria devoirNote1_1_2.R renamed as devoirNote1_2_2.R conforme o esperado.

Os arquivos afetados são quaisquer que sejam os glob no final da linha de comando.

No entanto, se você tiver, digamos 1_1_2 e 1_2_2 , a renomeação do primeiro falhará, pois colidiria com o próximo. Isso exigiria dar os nomes dos arquivos em ordem inversa ou alterá-los para algum formato não colidido primeiro e depois para trás, por exemplo, adicionando um caractere extra.

(* não é a ferramenta de renomeação util-linux. Veja aqui e aqui )

    
por 25.03.2017 / 18:32
0

Um script seria um exagero para dois movimentos (em lotes). Use o utilitário mmv :

mmv devoirNote1_2_"*" devoirNote1_3_#1
mmv devoirNote1_1_"*" devoirNote1_2_#1

Nessa ordem, é claro. Se houver muito mais do que dois movimentos, então um roteiro seria preferível.

    
por 25.03.2017 / 18:35
0

Aqui, fazemos uso do negative lookaheads para filtrar os arquivos *Note1_3_2.R e *Note1_4_2.R da lista de pesquisa.

O OP queria deixar o *Note1_4_2.R untouched = > nós não podemos tocar em um arquivo anterior também, isto é, o *Note1_3_2.R , já que não temos lugar para isso.

A lógica do loop for está lá para executar um reverse numeric sort no número do índice entre o 1 e o 2 para que possamos executar uma operação não destrutiva de mv.

perl -e '
   /(.*)_(\d+)_(.*)/ and
      rename $_, join "_", $1, $2+1, $3 or warn "Could not mv the file <<$_>>\n"
      for
         map  {                  $_->[0]                   }
         sort { $b->[2] <=> $a->[2] || $b->[1] <=> $a->[1] }
         map  {             [$_, /_(\d+)_(\d+)/]           }
         grep {     /^devoirNote1_(?![34]_1.R)\d+_\d+.R/   }
         <*.R>
'
    
por 25.03.2017 / 20:35