Как сделать так, чтобы все мои исходные файлы оставались в UTF-8 с окончанием строки Unix? - PullRequest
11 голосов
/ 22 января 2012

Я ищу некоторые инструменты командной строки для 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 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 для каждого файла?

Ответы [ 3 ]

12 голосов
/ 05 декабря 2012

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

Sublime Text 2 status bar

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

Sublime Text 2 commands

3 голосов
/ 22 января 2012

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

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

2 голосов
/ 27 января 2012

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

...