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 p
e possui um número após o p
que 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 perl
versã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/
- substituirxx
comyy
^
- 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 -v
para ver o que realmente está acontecendo ou simplesmente omita-o para operação silenciosa.
Responder2
Aqui está um awk
script 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 sed
por um p
seguido 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.