Как сделать так, чтобы все мои исходные файлы оставались в 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 C++, текст документа HTML, текст на английском языке и т. д.

$ tree -f -i -a -I node_modules --noreport -n | файл xargs | каталог grep -v./config.json: текст программы ASCII C++./debugserver.sh: текст ASCII./.gitignore: текст ASCII, без разделителей строк./lib/config.js: текст ASCII./lib/database.js: текст ASCII./lib/get_input.js: текст ASCII./lib/models/stream.js:     ASCII текст на английском языке./lib/serverconfig.js: текст ASCII./lib/server.js: текст ASCII./package.json: текст ASCII./public/index.html: текст документа HTML./src/config.coffee:        ASCII текст на английском языке./src/database.coffee:      ASCII текст на английском языке./src/get_input.coffee: текст на английском языке ASCII, с ограничителями строки CRLF./src/jtv.coffee:           ASCII текст на английском языке./src/models/stream.coffee: ASCII текст на английском языке./src/server.coffee: текст ASCII./src/serverconfig.coffee: текст ASCII./testserver.sh: текст ASCII./vendor/minify.json.js: текст программы ASCII C++ с разделителями строк CRLF

Но если я включу -i это не показывает мне терминаторы строки:

$ tree -f -i -a -I node_modules --noreport -n | файл xargs -i | каталог grep -v./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? А что такое текст / х-с ++? Есть ли способ вывести только charset=utf-8 а также line-terminators=LF для каждого файла?

3 ответа

Решение

Решение, которое я выбрал, - это два плагина Sublime Text 2 "EncodingHelper" и "LineEndings". Теперь я получаю как кодировку файла, так и окончание строк в строке состояния:

Строка состояния Sublime Text 2

Если кодировка неправильная, я могу File-> Save with Encoding. Если окончания строк неправильные, последний плагин поставляется с командами для изменения концов строк:

Sublime Text 2 команды

Если файл не имеет спецификации и "интересных символов" в объеме текста, который file смотрит на, file приходит к выводу, что это ASCII ISO-646 - строгое подмножество UTF-8. Вы можете обнаружить, что размещение спецификаций на всех ваших файлах стимулирует работу всех этих инструментов Windows; условное обозначение спецификации файла UTF-8, созданное в Windows. Или это может ухудшить ситуацию. Что касается х / с ++, то это просто file пытаюсь быть полезным и терпит неудачу. В вашем javascript есть что-то похожее на C++.

Apache Tika имеет детектор кодирования; вы могли бы даже использовать драйвер командной строки, который поставляется с ним в качестве альтернативы file, Он будет придерживаться типов MIME, а не переходить на C++.

Вместо 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.

Другие вопросы по тегам