Remova o padrão de caracteres no início e no final dos nomes de arquivos

Remova o padrão de caracteres no início e no final dos nomes de arquivos

Tenho vários arquivos que gostaria de renomear. Seus nomes de arquivos estão em um determinado formato:

p1.uniquenameA#blah_a
p2.uniquenameB#blah_b
p3.uniquenameC#blah_c
p4.uniquenameD#blah_d
p5.uniquenameE#blah_e
p6.uniquenameF#blah_f
p7.uniquenameG#blah_g
p8.uniquenameH#blah_h
p9.uniquenameI#blah_i
p10.uniquenameJ#blah_j

Há um prefixo antes de cada nome de arquivo exclusivo. Nesse caso, esse prefixo começa com a letra pe possui um número após o pque aumenta em um. Um ponto final ( .) separa o prefixo do nome de arquivo exclusivo. Há um sufixo após cada nome de arquivo exclusivo que começa com uma hashtag ( #). Gostaria de remover os prefixos até os pontos finais e também gostaria de remover os sufixos começando e incluindo as hashtags. Gostaria que os nomes de arquivos resultantes fossem apenas nomes de arquivos exclusivos entre os pontos e as tags hash como este:

uniquenameA
uniquenameB
uniquenameC
uniquenameD
uniquenameE
uniquenameF
uniquenameG
uniquenameH
uniquenameI
uniquenameJ

Sou novo em scripts, então se você pudesse explicar como o código funciona, além de fornecê-lo, eu agradeceria muito.

Responder1

Se você tiver a perlversão de rename(às vezes chamada anteriormente de prename), poderá aplicar uma substituição de Expressão Regular:

rename -n 's/^.*?\.(.*?)#.*/$1/' *

Se você não entende Expressões Regulares (REs), vale muito a pena aprendê-las.

  • s/xx/yy/- substituir xxcomyy
  • ^- corresponde a um início de linha implícito
  • .*?- combine uma string tão curta quanto possívelzero ou mais caracteres de qualquer coisasujeito ao resto da correspondência de padrões
  • \.- corresponde a um ponto literal .(o .caractere representaqualquer coisa, mas \.é um ponto literal)
  • (... )combine um padrão entre colchetes e atribua a ele um número de correspondência 1..9; posteriormente referenciado por $1(o segundo (... )seria $2, etc.)
  • #- caractere literal
  • .*- a partida mais longa que ézero ou mais caracteres de qualquer coisa(o .équalquer coisae as *médias _zero ou mais do item anterior)

Remova o -n("sem ação") quando estiver satisfeitoseriatrabalhar. Substitua-o por -vpara ver o que realmente está acontecendo ou simplesmente omita-o para operação silenciosa.

Responder2

Aqui está um awkscript que faz a tarefa:

Somente para impressão/depuração:

awk 'match($0,/(^[^\\.]+.)([^#]+)/,m){print "mv "$0" "m[2] }' input.txt    

Faça a renomeação:

awk 'match($0,/(^[^\\.]+.)([^#]+)/,m){system("mv "$0" "m[2])}' input.txt    

entrada.txt

p1.uniquenameA#blah_a
p2.uniquenameB#blah_b
p3.uniquenameC#blah_c
p4.uniquenameD#blah_d
p5.uniquenameE#blah_e
p6.uniquenameF#blah_f
p7.uniquenameG#blah_g
p8.uniquenameH#blah_h
p9.uniquenameI#blah_i
p10.uniquenameJ#blah_j

saída

mv p1.uniquenameA#blah_a uniquenameA
mv p2.uniquenameB#blah_b uniquenameB
mv p3.uniquenameC#blah_c uniquenameC
mv p4.uniquenameD#blah_d uniquenameD
mv p5.uniquenameE#blah_e uniquenameE
mv p6.uniquenameF#blah_f uniquenameF
mv p7.uniquenameG#blah_g uniquenameG
mv p8.uniquenameH#blah_h uniquenameH
mv p9.uniquenameI#blah_i uniquenameI
mv p10.uniquenameJ#blah_j uniquenameJ

Responder3

Aqui está uma solução usandosed

for i in *
do
    mv $i $( echo $i | sed 's/p[[:digit:]]*\.\([^#]*\)\#.*/\1/' )
done

O destino é criado procurando sedpor um pseguido por qualquer número de dígitos seguido por um ponto. Os personagens do período em diante até o #personagem sãolembreiem um registro, e todo o nome do arquivo é substituído pelolembreipersonagens.

informação relacionada