Pages

Sunday, January 17, 2010

Alternando arquivos entre codificações UTF-8 e ISO-8859-1

O um dos textos mais populares desse blog é que escrevi em 2006 explicando como converter arquivos entre as codificações UTF-8 e ISO-8859-1. Esse tópico vai revisitar o assunto. Algumas partes vão parecer cópias, é porque são cópias.

Não posso deixar de agradecer aos inúmeros comentários do tópico original. Foram esses comentários que me ajudaram a entender várias coisas que são apresentadas aqui. Enfim, a leitura dos comentários é fundamental para entender o motivo de eu ter repaginado esse tópico e para entender de onde vem algumas inspirações que serão expostas.

Convertendo o conteúdo do arquivo entre os formatos

O comando iconv é parte padrão de toda distribuição GNU/Linux.
A sintaxe básica é dada por:

iconv -f codificacao_de_origem -t codificacao_de_saida arquivo

Assim para converter UTF-8 para ISO-8859-1 temos:

iconv -f utf-8 -t iso-8859-1 arquivo

Para o contrário utilizamos:

iconv -f iso-8859-1 -t utf-8 arquivo

É necessário redirecionar a saida de arquivo para algum lugar, algo como:

iconv -f utf-8 -t iso-8859-1 arquivo > novo_arquivo

Identificando a codificação do arquivo

O comando iconv não é muito inteligente. Ele não sabe qual é a codificação original do arquivo. Resumindo, ele pode corromper um arquivo caso seja feita uma conversão dupla (ou tripla) de forma equivocada.

Para esses casos, apresento o comando file. Que me foi apresentado pelo Bob nos comentários do tópico original. A sintaxe é muito simples:

file --mime-encoding nome_do_arquivo

Se o arquivo não for um binário ele vai retornar qual é a codificação. E essa informação pode ser filtrada em um script para evitar conversões erradas entre formatos. O uso da opção "--mime-encoding" é opcional em arquivos de texto puro, mas não é no caso de um código fonte HTML, por exemplo. Ainda assim esse comando tem algumas particularidades. Por exemplo, ele identifica o .vimrc como um binário e não retorna qual é a codificação (que de fato não faz sentido em um binário), o problema é que o .vimrc é texto e ele pode te problemas de codificação.

Convertendo o nome dos arquivos entre os formatos

Para converter o nome dos arquivos entre as duas codificações, o comando é o convmv
A sintaxe á dada por:

convmv -t codificacao_de_saida -f codificacao_de_origem --notest nomes_dos_arquivos

Assim para converter UTF-8 para ISO-8859-1 temos:

convmv -t iso-8859-1 -f utf-8 --notest nomes_dos_arquivos

O inverso, ISO-8859-1 para UTF-8, a comando é dado por:

convmv -t utf-8 -f iso-8859-1 --notest nomes_dos_arquivos

onde nomes_dos_arquivos é a lista de todos os arquivos que deseja decodificar, inclusive, aceita-se asterisco. A opção "-r" permite realizar a operação recursivamente. Esse comando é inteligente o suficiente para não converter arquivos que estejam na codificação de destino.

Essa dica eu peguei aqui. Ao buscar a solução de um problema, o Sérgio escreveu o tópico. Uma grande contribuição para esse tópico e para o script abaixo.

CodeConvert

CodeConvert é um script para conversão entre os formatos mencionados aqui. Ele converte nomes dos arquivos e o conteúdo dos arquivos utilizando o comando file para evitar que ocorra conversão errada. Você pode ler o pegar o script CodeConvert nesse link.

Existe backup para todo arquivo convertido.
Arquivos somente são convertidos com o comando file diz que de fato o formato inicial é aquele imaginado pelo usuário. Assim, se tiver um arquivo em um formato diferente não será feita nenhuma modificação no arquivo.

O Benneh Carvalho modificou o script do Marcelo Oliveira após a dica do comando file. A idéia de incluir a conversão de nomes foi do Sérgio, e note que na época eu achei que não seria interessante por não saber que existia um comando pronto e inteligente para fazer a conversão dos nomes.

Enfim, espero que aproveitem o script. Usem-no no bom espírito da GNU General Public License.

[update]
A nova versão conta com a colaboração do John Robson, mais detalhes nesse outro tópico
[/update]

Conclusão

Eu escrevi o tópico original sem nenhuma intenção de que ele fosse chamar tanta atenção. E olha só o que temos hoje. O quanto de discussão gerou e tudo mais. E você acha que eu escrevi tudo que têm nos comentários de lá aqui ? Nada, veja por exemplo o uso do iconv em um programa em C++ em um trecho de código escrito pelo Rafael. O que eu posso dizer ?

Obrigado a todos pelas contribuições e que esse novo tópico, reescrito e ampliado, possa servir de base para novas conversas agradáveis e de ajuda a quem precisa.

E, por favor, se encontrar bugs e/ou melhores formas de fazer o que foi feito ali ou se tiver novas idéias para acrescentar, não deixe de divulgar por aqui o que pretende fazer ou o que fez...

Notas
  • Para os novatos que quiserem utilizar o CodeConvert, copie o conteúdo do script para um arquivo de texto do computador e salve com o nome CodeConvert (ou outro de sua preferência, esse será o nome do comando). Depois, defina o arquivo como executável, seja pelas propriedades do arquivo ou pelo terminal, executando o comando
    chmod +x CodeConvert.
    Observe também que alinha #!/bin/bash deve ser a primeira linha do arquivo.
  • Eu utilizei o vim para editar esse arquivo e eu uso a opção
    set fmr={{{,}}}
    no meu .vimrc. Assim, os {{{ e }}} definem começo e fim de dobras.

5 comments:

  1. Isto se chama ecosistema do Software Livre, cada vez mais interações gerando uma base de conhecimento crescente e de alta qualidade. Bom trabalho jovem!

    ReplyDelete
  2. Cara, vocês estão de parabéns!!! ficou muito legal...
    vai me ajudar bastante!!!

    P.s: Li o tópico antigo todo antes de ver esse aqui, acho que deveria ter um link lá avisando que existe essa versão melhorada aqui, você menciona o novo tópico mas não indica o caminho...:-P

    Valeu!!!

    ReplyDelete
  3. Andrax, bem observado.
    Acabo de colocar a informação no começo daquele tópico.

    ReplyDelete
  4. @Leandro,
    grato pelo comentário.

    ReplyDelete