Как убедиться, что все мои исходные файлы остаются UTF-8 с окончанием строки Unix?
Я ищу некоторые инструменты командной строки для Linux, которые могут помочь мне обнаружить и преобразовать файлы с наборов символов, таких как iso-8859-1 и windows-1252, в utf-8 и из концов строк Windows до окончаний строк Unix.
Причина, по которой я нуждаюсь в этом, - это то, что я работаю над проектами на серверах Linux через SFTP с редакторами в Windows (например, Sublime Text), которые просто постоянно закручивают эти вещи. Прямо сейчас я предполагаю, что половина моих файлов - utf-8, остальные - iso-8859-1 и windows-1252, поскольку кажется, что Sublime Text просто выбирает набор символов, с помощью которого хранятся файлы, которые он хранит, когда я его сохраняю. Окончаниями строк являются ВСЕГДА окончания строки Windows, даже если я указал в параметрах, что окончание строк по умолчанию - LF, поэтому около половины моих файлов имеют LF, а половина - CRLF.
Поэтому мне понадобится хотя бы инструмент, который бы рекурсивно просматривал мою папку проекта и предупреждал меня о файлах, которые отклоняются от utf-8 с концами строки LF, поэтому я мог бы вручную исправить это, прежде чем я вступлю в мои изменения в GIT.
Любые комментарии и личный опыт по этой теме также будут приветствоваться.
Спасибо
Изменить: У меня есть временное решение, в котором я использую tree
и file
для вывода информации обо всех файлах в моем проекте, но это довольно странно. Если я не включил параметр -i
для file
, тогда многие мои файлы получат разные результаты, такие как текст программы ASCII С++ и текст 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? А какой текст/x-С++? Есть ли способ, чтобы я мог выводить только charset=utf-8
и line-terminators=LF
для каждого файла?
Ответы
Ответ 1
В результате я получил два плагина Sublime Text 2 "EncodingHelper" и "LineEndings". Теперь я получаю как кодировку файла, так и конец строки в строке состояния:
![Sublime Text 2 status bar]()
Если кодировка неверна, я могу Файл- > Сохранить с кодировкой. Если строки заканчиваются неправильно, последний плагин содержит команды для изменения окончаний строки:
![Sublime Text 2 commands]()
Ответ 2
Если в файле нет спецификации и нет "интересных символов" в количестве текста, на которое смотрит file
, file
делает вывод, что это ASCII ISO-646 - строгий подмножество UTF-8. Вы можете обнаружить, что размещение спецификаций во всех ваших файлах побуждает все эти инструменты Windows вести себя; соглашение спецификации спецификации UTF-8, созданной в Windows. Или это может ухудшить ситуацию. Что касается x/С++, хорошо, что просто file
tryin 'будет полезен и не работает. У вас javascript есть что-то в нем, похожее на С++.
Apache Tika имеет детектор кодирования; вы даже можете использовать драйвер командной строки, который поставляется вместе с ним в качестве альтернативы file
. Он будет придерживаться MIME-типов, а не переходить на С++.
Ответ 3
Вместо file
попробуйте пользовательскую программу, чтобы проверить только то, что вы хотите. Вот быстрый хак, в основном основанный на несколько Google показов, которые, кстати, были написаны @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-битных кодировок - он просто бросает unknown
, если не будет ни чистого 7-битного ASCII, ни правильного UTF-8.