Este é um problema difícil, mas eu o tenho com muita frequência. Eu construí um conjunto de scripts com diferentes abordagens e vou mostrar um simples (ensureutf8 no contexto latino europeu)
- para cada arquivo, pergunte por seu tipo e charset (
file -i
) - decida o que fazer para casos comuns, mantendo um backup.
- em muitos casos ... não faça nada!
- em alguns casos, use um padrão (no exemplo CP1252 / latin1)
#!/usr/bin/perl
use strict;
my $charset;
for(@ARGV){
$charset="?";
next if /.bak$/;
my $type = 'file -b -i '$_''; ### use file -i for charset and type
if($type =~ /(\S+);\s+charset=(\S+)/){$type=$1; $charset=lc($2)};
next if($charset eq "utf-8") ;
next if($charset eq "binary") ;
next if($charset eq "us-ascii") ;
next if($type eq "application/postscript");
if($type eq "application/xml"){
rename($_ ,"$_.bak");
system ("xmllint --encode utf-8 '$_.bak' > '$_'\n") }
elsif($charset eq "non-iso" or $charset eq "unknown-8bit" ) {
rename($_ ,"$_.bak");
system ("iconv -f CP1252 -t utf-8 '$_.bak' > '$_'\n") } ## DANGER
elsif($charset eq "utf-16le"){
rename($_ ,"$_.bak");
system ("iconv -f $charset -t utf-8 '$_.bak' > '$_'\n") }
elsif($charset eq "iso-8859" or $charset eq "iso-8859-1"){
rename($_ ,"$_.bak");
system ("iconv -f latin1 -t utf-8 '$_.bak' > '$_'\n") }
else { print "HELP: '$type:$charset' '$_'\n"; }
}
Esta não é uma ferramenta universal, mas pode ser útil como ponto de partida para implementar sua própria heurística.