我正在寻找一些Linux的命令行工具,可以帮助我检测和转换字符集中的文件,如 iso-8859-1 和 windows-1252 到 utf-8 ,从Windows行结尾到Unix行结尾。
我需要这个的原因是我正在通过SFTP在Linux服务器上开展项目,在Windows上使用编辑器(如Sublime Text),这些项目只是不断地搞砸了。现在我猜我的一半文件是 utf-8 ,其余的是 iso-8859-1 和 windows-1252 因为它似乎Sublime Text只是选择字符集,当我保存文件时,文件包含哪些符号。行结尾总是Windows行结尾,即使我在选项中指定默认行结尾是 LF ,因此大约一半的文件有 LF ,一半是< EM> CRLF
所以我至少需要一个工具来递归扫描我的项目文件夹,并提醒我那些偏离 utf-8 并带有 LF 行结尾的文件,这样我就可以在我将更改提交给GIT之前手动修复它。
欢迎任何有关该主题的评论和个人经历。
由于
编辑 我有一个临时解决方案,我使用tree
和file
输出有关项目中每个文件的信息,但它有点不稳定。如果我没有为-i
添加file
选项,那么我的很多文件会得到不同的输出,例如 ASCII C ++程序文本和 HTML文档文本和英文文本等:
$ tree -f -i -a -I node_modules --noreport -n | xargs file | grep -v directory ./config.json: ASCII C++ program text ./debugserver.sh: ASCII text ./.gitignore: ASCII text, with no line terminators ./lib/config.js: ASCII text ./lib/database.js: ASCII text ./lib/get_input.js: ASCII text ./lib/models/stream.js: ASCII English text ./lib/serverconfig.js: ASCII text ./lib/server.js: ASCII text ./package.json: ASCII text ./public/index.html: HTML document text ./src/config.coffee: ASCII English text ./src/database.coffee: ASCII English text ./src/get_input.coffee: ASCII English text, with CRLF line terminators ./src/jtv.coffee: ASCII English text ./src/models/stream.coffee: ASCII English text ./src/server.coffee: ASCII text ./src/serverconfig.coffee: ASCII text ./testserver.sh: ASCII text ./vendor/minify.json.js: ASCII C++ program text, with CRLF line terminators
但如果我确实包含-i
,则不会显示行终止符:
$ tree -f -i -a -I node_modules --noreport -n | xargs file -i | grep -v directory ./config.json: text/x-c++; charset=us-ascii ./debugserver.sh: text/plain; charset=us-ascii ./.gitignore: text/plain; charset=us-ascii ./lib/config.js: text/plain; charset=us-ascii ./lib/database.js: text/plain; charset=us-ascii ./lib/get_input.js: text/plain; charset=us-ascii ./lib/models/stream.js: text/plain; charset=us-ascii ./lib/serverconfig.js: text/plain; charset=us-ascii ./lib/server.js: text/plain; charset=us-ascii ./package.json: text/plain; charset=us-ascii ./public/index.html: text/html; charset=us-ascii ./src/config.coffee: text/plain; charset=us-ascii ./src/database.coffee: text/plain; charset=us-ascii ./src/get_input.coffee: text/plain; charset=us-ascii ./src/jtv.coffee: text/plain; charset=us-ascii ./src/models/stream.coffee: text/plain; charset=us-ascii ./src/server.coffee: text/plain; charset=us-ascii ./src/serverconfig.coffee: text/plain; charset=us-ascii ./testserver.sh: text/plain; charset=us-ascii ./vendor/minify.json.js: text/x-c++; charset=us-ascii
为什么它会显示 charset = us-ascii 而不是 utf-8 ?什么是 text / x-c ++ ?有没有办法只能为每个文件输出charset=utf-8
和line-terminators=LF
?
答案 0 :(得分:12)
我最终得到的解决方案是两个Sublime Text 2插件“EncodingHelper”和“LineEndings”。我现在在状态栏中获得文件编码和行结尾:
如果编码错误,我可以文件 - &gt;使用编码保存。如果行结尾是错误的,后一个插件会带有更改行结尾的命令:
答案 1 :(得分:3)
如果文件没有BOM,并且file
查看的文本数量中没有“有趣字符”,file
会认为它是 ASCII ISO-646 - UTF-8的严格子集。您可能会发现将BOM放在所有文件上会鼓励所有这些Windows工具运行;源自Windows的UTF-8文件上的BOM的约定。或者它可能会使事情变得更糟。至于x / c ++,嗯,只是file
试着帮助和失败。你的javascript里面有一些看起来像C ++的东西。
Apache Tika有一个编码检测器;您甚至可以使用它附带的命令行驱动程序作为file
的替代方法。它将坚持使用MIME类型,而不是偏离C ++。
答案 2 :(得分:2)
尝试自定义程序来检查您想要的内容,而不是file
。这是一个快速入侵,主要基于some Google hits,偶然由@ikegami撰写。
#!/usr/bin/perl
use strict;
use warnings;
use Encode qw( decode );
use vars (qw(@ARGV));
@ARGV > 0 or die "Usage: $0 files ...\n";
for my $filename (@ARGV)
{
my $terminator = 'CRLF';
my $charset = 'UTF-8';
local $/;
undef $/;
my $file;
if (open (F, "<", $filename))
{
$file = <F>;
close F;
# Don't print bogus data e.g. for directories
unless (defined $file)
{
warn "$0: Skipping $filename: $!\n;
next;
}
}
else
{
warn "$0: Could not open $filename: $!\n";
next;
}
my $have_crlf = ($file =~ /\r\n/);
my $have_cr = ($file =~ /\r(?!\n)/);
my $have_lf = ($file =~ /(?!\r\n).\n/);
my $sum = $have_crlf + $have_cr + $have_lf;
if ($sum == 0)
{
$terminator = "no";
}
elsif ($sum > 2)
{
$terminator = "mixed";
}
elsif ($have_cr)
{
$terminator = "CR";
}
elsif ($have_lf)
{
$terminator = "LF";
}
$charset = 'ASCII' unless ($file =~ /[^\000-\177]/);
$charset = 'unknown'
unless eval { decode('UTF-8', $file, Encode::FB_CROAK); 1 };
print "$filename: charset $charset, $terminator line endings\n";
}
请注意,这没有传统8位编码的概念 - 如果它既不是纯粹的7位ASCII也不是正确的UTF-8,它只会抛出unknown
。