Como encontrar a codificação de um arquivo em Unix via script (s)
Pergunta
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 file
não é capaz de fazer isso.
A codificação que é de interesse para mim é: ISO-8859-1. Se a codificação é qualquer outra coisa, eu quero mover o arquivo para outro diretório.
Solução
Parece que você está procurando enca
. Ele pode adivinhar e até mesmo converter entre codificações. Basta olhar para a página homem .
Ou, na sua falta, o uso file -i
(linux) ou file -I
(OSX). Que o produto será informações do tipo MIME para o arquivo, que também incluirá a codificação de caracteres-set. Eu encontrei um man-page por isso, também:)
Outras dicas
file -bi <file name>
Se você gostaria de fazer isso por um monte de arquivos
for f in `find | egrep -v Eliminate`; do echo "$f" ' -- ' `file -bi "$f"` ; done
uchardet - uma codificação biblioteca detector portado do Mozilla
.Uso:
~> uchardet file.java
UTF-8
Várias distribuições Linux (Debian / Ubuntu, OpenSuse-packman, ...) fornecer binários.
aqui é um exemplo de script usando -I arquivo e iconv que trabalha em MacOSX Para a sua pergunta que você precisa usar mv 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
É muito difícil determinar se é iso-8859-1. Se você tem um texto com apenas 7 bit caracteres que também poderia ser iso-8859-1, mas você não sabe. Se você tem 8 caracteres bit, em seguida, existem os personagens região superior em codificações de ordem também. Porém você teria que usar um dicionário para obter uma melhor adivinhar qual palavra é e determinar a partir daí que carta que deve ser. Finalmente, se você detectar que poderia ser utf-8 do que você tem certeza 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
Com Python, você pode usar o módulo chardet: https://github.com/chardet/chardet
No Debian você também pode usar: encguess
:
$ encguess test.txt
test.txt US-ASCII
Isto não é algo que você pode fazer em uma maneira infalível. Uma possibilidade seria examinar cada personagem no arquivo para garantir que ele não contém quaisquer caracteres no 0x00 - 0x1f
faixas ou 0x7f -0x9f
mas, como eu disse, isso pode ser verdade para qualquer número de arquivos, incluindo pelo menos uma outra variante do ISO8859.
Outra possibilidade é procurar palavras específicas no arquivo em todos os idiomas suportados e veja se você pode encontrá-los.
Assim, por exemplo, encontrar o equivalente do Inglês "e", "mas", "a", "de" e assim por diante em todas as línguas suportadas do 8859-1 e ver se eles têm um grande número de ocorrências dentro do arquivo.
Eu não estou falando sobre tradução literal, tais como:
English French
------- ------
of de, du
and et
the le, la, les
apesar de que é possível. Estou falando de palavras na língua-alvo (pelo que sei, islandês não tem nenhuma palavra para "e" - você provavelmente teria que usar sua palavra para "peixe" [desculpa que é um pouco estereotipada, eu não fiz significa qualquer ofensa, apenas ilustrando um ponto]).
Se você está falando de arquivos XML (ISO-8859-1), o XML-declaração dentro deles especifica a codificação: <?xml version="1.0" encoding="ISO-8859-1" ?>
Assim, você pode usar expressões regulares (por exemplo, com perl
) para verificar todos os arquivos para tal especificação.
Mais informações podem ser encontradas aqui: Como determinar arquivo de texto codificação .
Para converter codificar a partir de 8859 para ASCII:
iconv -f ISO_8859-1 -t ASCII filename.txt
Eu sei que você está interessado em uma resposta mais geral, mas o que é bom em ASCII é geralmente bom em outras codificações. Aqui é um Python one-liner para determinar se a entrada padrão é ASCII. (Eu tenho certeza que isso funciona em Python 2, mas eu só testei em 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
Em Cygwin, isso parece que funciona para mim:
find -type f -name "<FILENAME_GLOB>" | while read <VAR>; do (file -i "$<VAR>"); done
Exemplo:
find -type f -name "*.txt" | while read file; do (file -i "$file"); done
Você poderia tubo que a awk e criar um comando iconv para converter tudo para utf8, a partir de qualquer fonte de codificação suportada por 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
Você pode extrair codificação de um único arquivo com o comando de arquivo. Eu tenho um arquivo sample.html com:
$ file sample.html
sample.html: documento HTML, UTF-8 Unicode texto, com linhas muito longas
$ file -b sample.html
HTML documento, UTF-8 texto Unicode, com linhas muito longas
$ file -bi sample.html
text / html; charset = utf-8
$ file -bi sample.html | awk -F'=' '{print $2 }'
utf-8
Eu estou usando o seguinte script para
- Encontre todos os arquivos que correspondem FILTER com SRC_ENCODING
- Criar um backup deles
- convertê-los para DST_ENCODING
- (opcional) Retire os backups
.
#!/bin/bash -xe
SRC_ENCODING="iso-8859-1"
DST_ENCODING="utf-8"
FILTER="*.java"
echo "Find all files that match the encoding $SRC_ENCODING and filter $FILTER"
FOUND_FILES=$(find . -iname "$FILTER" -exec file -i {} \; | grep "$SRC_ENCODING" | grep -Eo '^.*\.java')
for FILE in $FOUND_FILES ; do
ORIGINAL_FILE="$FILE.$SRC_ENCODING.bkp"
echo "Backup original file to $ORIGINAL_FILE"
mv "$FILE" "$ORIGINAL_FILE"
echo "converting $FILE from $SRC_ENCODING to $DST_ENCODING"
iconv -f "$SRC_ENCODING" -t "$DST_ENCODING" "$ORIGINAL_FILE" -o "$FILE"
done
echo "Deleting backups"
find . -iname "*.$SRC_ENCODING.bkp" -exec rm {} \;
Com Perl, uso Encode :: Detectar.