我见过很多将文本转换为 UTF-8 的方法,但它们都需要指定当前使用的文本编码。
有没有一种方法可以将多个文件批量转换为UTF-8,而不必关心它们以前使用过什么?
答案1
这是一个很难的问题,但我经常遇到这个问题。我用不同的方法构建了一组脚本,我将展示一个简单的脚本(确保欧洲拉丁语环境中的utf8)
- 对于每个文件,询问其类型和字符集 (
file -i
) - 决定如何处理常见情况,并保留备份。
- 在很多情况下...什么也不做!
- 在某些情况下使用默认值(在示例中为 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"; }
}
这不是一个通用工具,但它可能有助于作为实现您自己的启发式方法的起点。