11

estoy en busca de algunas herramientas de línea de comandos para Linux que me puedan ayudar a detectar y convertir archivos de juegos de caracteres como iso-8859-1 y windows-1252 a UTF-8 y desde finales de línea de Windows a terminaciones de línea Unix.¿Cómo me aseguro de que todos mis archivos fuente permanezcan UTF-8 con terminaciones de línea Unix?

La razón por la que necesito esto es porque estoy trabajando en proyectos en servidores Linux a través de SFTP con editores en Windows (como Sublime Text) que constantemente arruina todo esto. En este momento estoy adivinando cerca de la mitad de mis archivos son UTF-8, el resto son iso-8859-1 y windows-1252 como parece Sublime Text se acaba de recoger el conjunto de caracteres por los que el archivo contiene símbolos cuando Lo guardo. Las terminaciones de línea son SIEMPRE terminaciones de línea de Windows aunque he especificado en las opciones que las terminaciones de línea predeterminadas son LF, entonces aproximadamente la mitad de mis archivos tienen LF y la otra mitad son CRLF.

Así que necesitaría al menos una herramienta que forma recursiva escanear mi carpeta del proyecto y me avise de los archivos que se desvían de UTF-8 con LF finales de línea para que pudiera fijar manualmente que antes de comprometerme mis cambios GIT.

Todos los comentarios y experiencias personales sobre el tema también serían bienvenidos.

Gracias


Editar: yo tenemos una solución temporal en el lugar donde uso tree y file a la información de salida acerca de cada archivo en mi proyecto, pero es un poco torcidas. Si no incluyo la opción -i para file entonces un montón de mis archivos se pone de salida diferente como ASCII C++ texto del programa y documento HTML texto y Inglés texto etc:

 
$ 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 

Pero si no incluir -i que no me muestra las terminaciones de línea:

 
$ 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 

también por qué se muestra charset = us-ascii y no utf-8? ¿Y qué es text/x-C++? ¿Hay alguna forma de que solo produzca charset=utf-8 y line-terminators=LF para cada archivo?

+0

En cuanto a una solución, tal vez usted podría incluir un comentario con un código de carácter decididamente no-ASCII (el símbolo de copyright viene a la mente) y guardar como UTF-8 - tal vez esto sea suficiente para que Sublime Text deje de adivinar tantas cosas. – tripleee

+1

¡Tampoco puedo, por mi vida, obtener Sublime Text para usar saltos de línea Unix para el amor de Dios! "default_line_ending": "unix" debería funcionar! – jlarson

Respuesta

12

La solución que terminó con los dos es Sublime Text 2 plugins y "LineEndings" "" EncodingHelper. Ahora recibe tanto la codificación de archivos y finales de línea en la barra de estado:

Sublime Text 2 status bar

Si la codificación está mal, puedo Archivo-> Guardar con codificación. Si los finales de línea están equivocados, este último plugin viene con comandos para cambiar los finales de línea:

Sublime Text 2 commands

+0

Apesadumbrado, el complemento "LineEndings" se ha ido ... – Hubro

3

Si un archivo no tiene ninguna lista de materiales, y no hay '' personajes interesantes dentro de la cantidad de texto que file mira, file llega a la conclusión de que es ASCII ISO-646 - un subconjunto estricto de UTF-8. Puede encontrar que poner listas de materiales en todos sus archivos alienta a todas estas herramientas de Windows a comportarse; la convención de una BOM en un archivo UTF-8 originado en Windows. O podría empeorar las cosas. En cuanto a x/C++, bueno, eso es solo file tratando de ser útil y fallar. Usted javascript tiene algo que se parece a C++.

Apache Tika tiene un detector de codificación; incluso podría usar el controlador de línea de comandos que viene con él como alternativa al file. Se apegará a los tipos MIME y no vagará a C++.

+0

Gracias por las explicaciones. En cuanto al uso del detector de codificación de Apache Tika ... Se siente como adquirir un crucero para cruzar un charco. Lo que aparentemente estoy buscando es una herramienta de línea de comando para analizar archivos que me dará el resultado que estoy buscando, que es la codificación de caracteres y los terminadores de línea – Hubro

+0

Solo asegúrese de que el charco no tenga un arrecife. Realmente, usar su CLI es simplemente 'usar un comando'. No recuerdo si icu4c incluye un comando que sería una alternativa competitiva, o si usar iconv con las opciones correctas le daría un error claro para los que no sean UTF-8. – bmargulies

+0

Tenga en cuenta que 'file' a veces usa heurísticas bastante toscas; su ejemplo' x-C++ 'lo muestra adivinando incorrectamente. Si sabe exactamente lo que está buscando, unos simples comandos 'grep' pueden ayudarlo a categorizar sus archivos. – tripleee

2

En lugar de file, intente con un programa personalizado para comprobar solo las cosas que desea. Aquí hay un truco rápido, basado principalmente en some Google hits, que fueron escritos accidentalmente por @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"; 
} 

Tenga en cuenta que esto no tiene ningún concepto de legado codificaciones de 8 bits - simplemente tirará unknown si no es ni pura ASCII de 7 bits ni adecuada UTF-8.

Cuestiones relacionadas