Estou padronizando o nome de vários arquivos de uma vez, então escrevi uma regex para perl-rename
:
perl-rename 'y/A-Z/a-z/; s/ã|á|â/a/g; s/é|ê/e/g; s/í/i/g; s/õ|ó/o/g; s/ú/u/g; s/ç/c/g; s/(?<=\d-)*\s/_/g; s/_+/_/g; s/(?<=\d)_/-/' *
Está funcionando exatamente como esperado:
2024-12-01 certidão de matrícula -> 2024-12-01-certidao_de_matricula
No entanto, pensei que poderia ser simplificado um pouco, então pensei nisso:
perl-rename 'y/A-Z/a-z/; y/ãáâéêíõóúç/aaaeeioouc/; s/(?<=\d-)*\s/_/g; s/_+/_/g; s/(?<=\d)_/-/' *
Os resultados, no entanto, não atenderam às minhas expectativas. Por exemplo:
2024-12-01 certidão de matrícula -> 2024-12-01-certidaao_de_matraccula
Por que o segundo comando não está funcionando, já que ele deveria estar fazendo uma transliteração direta de cada caractere acentuado? Não consigo nem entender o resultado. Obrigado antecipadamente.
Isso acontece porque o Perl não sabe que deve tratar os nomes de arquivo como UTF-8. Em vez disso, ele olha para os bytes individuais, então você obtém substituições parciais e duplicatas. Por exemplo, considere isto:
Aqui, a entrada é
\xc3\xa4:\xc3\xb6:\xc3\xa4
e oy/ä/x/
é tomado comoy/\xc3\xa4/x/
(com o lado direitox
implicitamente duplicado). O resultado é que o UTF-8ä
se transforma emxx
, quando ambos os bytes são substituídos individualmente, e o UTF-8ö
quebra quando apenas o primeiro byte é substituído.O
s///
comando funciona porque ele procura a string inteira a ser substituída, então não importa se ela é interpretada como um caractere ou dois bytes.Você consertaria isso adicionando
use utf8
ou-Mutf8
para informar ao Perl que a fonte está em UTF-8, e a-C
opção de informar que stdin/stdout estão em UTF-8.Com o script de renomeação, você provavelmente não conseguirá usar
-C
, então use aPERL_UNICODE
variável de ambiente, por exemplo, withexport PERL_UNICODE=AS
(para argumentos e Stdin/out), e incluause utf8
no seu comando de renomeação e torça para que funcione.