Como encontrar a codificação de um arquivo no Unix via script (s)

Eu preciso encontrar a codificação de todos os arquivos que são colocados em um diretório. Existe uma maneira de encontrar a codificação usada?

O comando de file não é capaz de fazer isso.

A codificação que me interessa é: ISO-8859-1. Se a codificação é outra coisa, eu quero mover o arquivo para outro diretório.

Parece que você está procurando por enca . Pode adivinhar e até converter entre codificações. Basta olhar para a página do manual .

Ou, na falta disso, use o file -i (linux) ou file -I (osx). Isso gerará informações do tipo MIME para o arquivo, que também includeá a codificação do conjunto de caracteres. Eu encontrei uma página de manual para isso também 🙂

 file -bi  

Se você gosta de fazer isso por um monte de arquivos

 for f in `find | egrep -v Eliminate`; do echo "$f" ' -- ' `file -bi "$f"` ; done 

uchardet – Uma biblioteca de detetores de codificação portada da Mozilla.

Uso:

 ~> uchardet file.java UTF-8 

Várias distribuições Linux (Debian / Ubuntu, OpenSuse-packman, …) fornecem binários.

aqui está um script de exemplo usando o arquivo -I e iconv que funciona no MacOsX Para sua pergunta você precisa usar mv em vez de iconv

 #!/bin/bash # 2016-02-08 # check encoding and convert files for f in *.java do encoding=`file -I $f | cut -f 2 -d";" | cut -f 2 -d=` case $encoding in iso-8859-1) iconv -f iso8859-1 -t utf-8 $f > $f.utf8 mv $f.utf8 $f ;; esac done 

É realmente difícil determinar se é iso-8859-1. Se você tem um texto com apenas 7 bits que também podem ser iso-8859-1, mas você não sabe. Se você tiver 8 caracteres de bits, os caracteres da região superior também existem nas codificações de ordem. Portanto, você teria que usar um dictionary para adivinhar qual palavra é e determinar a partir de qual letra deve ser. Finalmente, se você detectar que pode ser utf-8, você tem certeza de que não é iso-8859-1

A codificação é uma das coisas mais difíceis de fazer porque você nunca sabe se nada está lhe dizendo

Se você estiver falando sobre arquivos XML (ISO-8859-1), a declaração XML dentro deles especifica a codificação:
Assim, você pode usar expressões regulares (por exemplo, com perl ) para verificar cada arquivo para tal especificação.
Mais informações podem ser encontradas aqui: Como determinar a codificação do arquivo de texto .

Com o Python, você pode usar o módulo chardet: https://github.com/chardet/chardet

Isso não é algo que você possa fazer de uma maneira infalível. Uma possibilidade seria examinar cada caractere no arquivo para garantir que ele não contenha nenhum caractere nos intervalos 0x00 - 0x1f ou 0x7f -0x9f , mas, como eu disse, isso pode ser verdade para qualquer número de arquivos, incluindo pelo menos uma outra variante da ISO8859.

Outra possibilidade é procurar palavras específicas no arquivo em todos os idiomas suportados e ver se você consegue encontrá-los.

Assim, por exemplo, encontre o equivalente do inglês “and”, “but”, “to”, “of” e assim por diante em todos os idiomas suportados do 8859-1 e veja se eles têm um grande número de ocorrências dentro do Arquivo.

Não estou falando de tradução literal como:

 English French ------- ------ of de, du and et the le, la, les 

embora isso seja possível. Estou falando de palavras comuns na língua alvo (pelo que sei, o islandês não tem palavras para “e” – você provavelmente teria que usar a palavra deles para “peixe” [desculpe, isso é um pouco estereotipado, eu não fiz significa qualquer ofensa, apenas ilustrando um ponto]).

Eu sei que você está interessado em uma resposta mais geral, mas o que é bom em ASCII geralmente é bom em outras codificações. Aqui está um one-liner do Python para determinar se a input padrão é ASCII. (Tenho certeza que isso funciona no Python 2, mas eu testei apenas no Python 3.)

 python -c 'from sys import exit,stdin;exit()if 128>max(c for l in open(stdin.fileno(),"b") for c in l) else exit("Not ASCII")' < myfile.txt 

No Cygwin, parece que funciona para mim:

 find -type f -name "" | while read ; do (file -i "$"); done 

Exemplo:

 find -type f -name "*.txt" | while read file; do (file -i "$file"); done 

Você pode canalizar isso para o awk e criar um comando iconv para converter tudo para o utf8, a partir de qualquer codificação de origem suportada pelo iconv.

Exemplo:

 find -type f -name "*.txt" | while read file; do (file -i "$file"); done | awk -F[:=] '{print "iconv -f "$3" -t utf8 \""$1"\" > \""$1"_utf8\""}' | bash 

No Debian você também pode usar: encguess :

 $ encguess test.txt test.txt US-ASCII 

Você pode extrair a codificação de um único arquivo com o comando file. Eu tenho um arquivo sample.html com:

 $ file sample.html 

sample.html: documento HTML, texto Unicode UTF-8, com linhas muito longas

 $ file -b sample.html 

Documento HTML, texto Unicode UTF-8, com linhas muito longas

 $ file -bi sample.html 

text / html; charset = utf-8

 $ file -bi sample.html | awk -F'=' '{print $2 }' 

utf-8

Com Perl, use Encode :: Detect.