Linux'ta komut dosyası aracılığıyla bir dosyanın kodlamasını nasıl bulabilirim?


303

Bir dizine yerleştirilen tüm dosyaların kodlamasını bulmalıyım. Kullanılan kodlamayı bulmanın bir yolu var mı?

fileKomut bunu yapmak mümkün değildir.

Beni ilgilendiren kodlama: ISO-8859-1. Kodlama başka bir şeyse, dosyayı başka bir dizine taşımak istiyorum.


1
Ne tür bir komut dosyası dili kullanmak istediğinize dair bir fikriniz varsa, sorunuzu o dilin adıyla etiketleyin. Bu yardımcı olabilir ...
MatrixFrog

1
Ya da belki sadece bir kabuk senaryosu oluşturmaya çalışıyor?
Şalom Craimer

1
Bu da “hangi kodlama dili” ne bir cevap olacaktır.
bignose

7
Belki bu cevapla ilgili değil, genel olarak bir ipucu: Tüm şüphenizi tek bir kelimeyle (burada "kodlama") açıklayabiliyorsanız, sadece yapın apropos encoding. Tüm sayfaların başlıklarını ve açıklamalarını arar. Benim makinede Bunu yaparken, onların açıklamaları bakılırsa, bana yardımcı olabilecek 3 araçları görmek: chardet, chardet3, chardetect3. Sonra, man chardetmanpage'i okuyup okuyarak bana chardetihtiyacım olan yardımcı program olduğunu söyler .
John Red

1
Bir dosyanın içeriğini değiştirdiğinizde kodlama değişebilir. Örneğin vi'de, basit bir c programı yazarken, muhtemelen us-ascii, ama bir Çince yorum satırı ekledikten sonra, olur utf-8. filedosya içeriğini ve tahminini okuyarak kodlamayı söyleyebilir.
Eric Wang

Yanıtlar:


419

Kulağa aradığınız gibi geliyor enca. Tahmin edebilir ve hatta kodlamalar arasında dönüştürebilir. Sadece man sayfasına bak .

Ya da başarısız olursa, file -i(linux) veya file -I(osx) kullanın. Bu, karakter kümesi kodlamasını da içerecek olan dosya için MIME türü bilgiler verir. Ben de bunun için bir man-sayfası buldum :)


1
Man sayfasına göre, ISO 8559 setini biliyor. Belki biraz daha az imleç okumak :-)
bignose

5
Enca kulağa ilginç geliyor. Maalesef algılama çok dile bağlı gibi görünüyor ve desteklenen diller kümesi çok büyük değil. Mine (de) eksik :-( Her neyse cool tool.
er4z0r


6
encaİngilizce yazılmış bir dosyayı analiz etmek için tamamen işe yaramaz gibi görünüyor, ancak Estonya'da bir şeye bakıyorsanız, tüm sorunlarınızı çözebilir. Çok yararlı bir araç, bu ... </sarcasm>
cbmanica

6
@vladkras utf-8 dosyanızda ascii olmayan karakter yoksa, o zaman
ascii'den

85
file -bi <file name>

Bunu bir grup dosya için yapmak isterseniz

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

Ancak, dosya xml dosyasıysa, xml bildiriminde "encoding = 'iso-8859-1' özniteliğine sahipse, dosya komutu gerçek kodlama utf-8 olsa bile bunun bir iso dosyası olduğunu söyler ...
Per

6
-B argümanını neden kullanıyorsunuz? Sadece -i * dosyasını yaparsanız, her dosya için tahmin edilen karakter kümesini çıktılar.
Hans-Peter Störr

4
Ben de -b argümanını merak ettim. Man sayfası bunun "kısa" anlamına geldiğini söylüyorDo not prepend filenames to output lines
craq

1
Dosya çıktısını ayrıştırmaya gerek yok, file -b --mime-encodingsadece karakter kümesi kodlamasını çıktılar
jesjimher

-b 'kısa ol' anlamına gelir, bu da temel olarak az önce verdiğiniz dosya adını vermeyin demektir.
Nikos

36

uchardet - Mozilla'dan taşınan bir kodlama dedektörü kütüphanesi.

Kullanımı:

~> uchardet file.java 
UTF-8

Çeşitli Linux dağıtımları (Debian / Ubuntu, OpenSuse-packman, ...) ikili dosyalar sağlar.


1
Teşekkürler! Daha fazla paketten memnun değilim, ama sudo apt-get install uchardeto kadar kolay ki endişelenmemeye karar verdim ...
adaçayı

Ben sadece yukarıdaki bir yorumda söylediğim gibi: uchardet yanlışlıkla bir dosyanın kodlama "windows-1252" olduğunu söyledi, ancak ben açıkça UTF-8 olarak bu dosyayı kaydetti. uchardet, "en azından size saçmalıklarınızı tamamladığınızı söyleyen bir ipucu verecek" 0.4641618497109827 güvenle "bile söylemiyor. dosya, enca ve encguess düzgün çalıştı.
Algoman

uchardetbüyük bir avantaja sahiptir fileve encasadece başlangıcın aksine tüm dosyayı analiz eder (sadece 20GiB dosyasıyla denendi).
tuxayo

10

MacOsX üzerinde çalışan -I ve iconv dosyasını kullanan örnek bir komut dosyasıdır. Sorunuz için iconv yerine mv kullanmanız gerekiyor

#!/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

6
file -b --mime-encodingsadece karakter seti çıktılar, böylece tüm boru işlemeyi önleyebilirsiniz
jesjimher

1
Teşekkürler. MacOS'ta belirtildiği gibi bu çalışmaz: file -b --mime-encoding Kullanım: dosya [-bchikLNnprsvz0] [-e test] [-f namefile] [-F separator] [-m magicfiles] [-M magicfiles ] dosya ... dosya -C -m magicfiles Daha fazla bilgi için `` file --help '' dosyasını deneyin.
Wolfgang Fahl

6

İso-8859-1 olup olmadığını belirlemek gerçekten zor. İso-8859-1 de olabilecek sadece 7 bit karakterli bir metniniz varsa, ancak bilmiyorsunuzdur. 8 bit karakterleriniz varsa, üst bölge karakterleri de sipariş kodlamasında bulunur. Bu nedenle, hangi kelimenin olduğunu daha iyi tahmin etmek ve oradan hangi harfin olması gerektiğini belirlemek için bir sözlük kullanmanız gerekir. Son olarak bunun utf-8 olabileceğini tespit ederseniz iso-8859-1 olmadığından emin olabilirsiniz.

Kodlama yapılması en zor şeylerden biridir çünkü size hiçbir şeyin söylemediğini asla bilemezsiniz


Kuvvet kırmaya çalışmak yardımcı olabilir. Aşağıdaki komut, WIN veya ISO ile başlayan adlara sahip tüm ecncoding biçimlerinden UTF8'e dönüştürmeyi dener. Daha sonra, doğru kodlamaya bir ipucu arayan çıktıyı manuel olarak kontrol etmek gerekir. Elbette, uygun bir şey için ISO veya WIN'in yerine filtre uygulanmış formatları değiştirebilir veya grep komutunu kaldırarak filtreyi kaldırabilirsiniz. $ için i (iconv -l | kuyruk -n +2 | grep "(^ ISO \ | ^ WIN)" | sed -e 's / \ / \ ///'); echo $ i yap; iconv -f $ i -t UTF8 santos; yapılan;
ndvo

5

Debian'da şunları da kullanabilirsiniz encguess:

$ encguess test.txt
test.txt  US-ASCII

uchardetUbuntu'ya yükledim ve dosyamın olduğunu söyledi WINDOWS-1252. Bunun yanlış olduğunu biliyorum çünkü Kate'i test etmek için UTF-16 olarak sakladım. Ancak, encguessdoğru tahmin edin ve Ubuntu 19.04'te önceden kurulmuştur.
Nagev

5

Kodlamayı 8859'dan ASCII'ye dönüştürmek için:

iconv -f ISO_8859-1 -t ASCII filename.txt


3

Bu kusursuz bir şekilde yapabileceğiniz bir şey değil. Bir olasılık da aralıklarında herhangi bir karakter içermediğinden emin olmak için dosyada her karakter incelemek olacağını 0x00 - 0x1fya 0x7f -0x9fdediğim gibi bu iso8859 en az birinin diğer çeşitleri dahil, dosyaların herhangi bir sayı için doğru olabilir, ama.

Başka bir olasılık, dosyada desteklenen tüm dillerde belirli kelimeleri aramak ve bulabileceğinizi görmek.

Örneğin, 8859-1'in tüm desteklenen dillerinde İngilizce "ve", "ancak", "ila", "ve" eşdeğerlerini bulun ve bunların içinde çok sayıda tekrar olup olmadığını görün dosya.

Aşağıdaki gibi gerçek çeviriden bahsetmiyorum:

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

bu mümkün olsa da. Hedef dilde sık kullanılan kelimelerden bahsediyorum (bildiğim kadarıyla, İzlandaca "ve" için bir kelime yok - muhtemelen "balık" için kelimelerini kullanmak zorunda kalacaksınız [üzgünüm, bu biraz basmakalıp, ben yapmadım sadece bir noktayı gösteren herhangi bir suç anlamına gelir]).


2

Daha genel bir cevapla ilgilendiğinizi biliyorum, ancak ASCII'de iyi olan diğer kodlamalarda genellikle iyidir. Standart girişin ASCII olup olmadığını belirlemek için bir Python tek astarı. (Bunun Python 2'de çalıştığından eminim, ancak sadece Python 3'te test ettim.)

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

2

XML dosyaları (ISO-8859-1) hakkında konuşuyorsanız, içindeki XML bildirimi kodlamayı belirtir: <?xml version="1.0" encoding="ISO-8859-1" ?>
Bu nedenle, perlher dosyayı bu tür özellikler için kontrol etmek için normal ifadeleri (örn. İle ) kullanabilirsiniz.
Daha fazla bilgi burada bulunabilir: Metin Dosyası Kodlamasını Belirleme .


bu satırın hangi kodlamayı kullandığını bilmeyen biri tarafından kopyalanıp yapıştırılabileceği iyi.
Algoman

Dikkat kelimesi, üstteki bildirim hakkında hiçbir şey GERÇEKTEN bu şekilde kodlanmış dosyayı garanti etmez. Gerçekten, gerçekten kodlamayı önemsiyorsanız, bunu kendiniz doğrulamanız gerekir.
Jazzepi

2

Php aşağıdaki gibi kontrol edebilirsiniz:

Kodlama listesini açıkça belirtme:

php -r "echo 'probably : ' . mb_detect_encoding(file_get_contents('myfile.txt'), 'UTF-8, ASCII, JIS, EUC-JP, SJIS, iso-8859-1') . PHP_EOL;"

Daha doğru "mb_list_encodings":

php -r "echo 'probably : ' . mb_detect_encoding(file_get_contents('myfile.txt'), mb_list_encodings()) . PHP_EOL;"

Burada ilk örnekte, eşleşen olabilecek kodlamaların (liste sırasını algıla) bir listesini koyduğumu görebilirsiniz. Daha doğru sonuç almak için tüm olası kodlamaları şu yolla kullanabilirsiniz: mb_list_encodings ()

Not mb_ * işlevleri php-mbstring gerektirir

apt-get install php-mbstring

0

Cygwin'de bu benim için çalışıyor gibi görünüyor:

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

Misal:

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

Iconv tarafından desteklenen herhangi bir kaynak kodlamasından, her şeyi utf8'e dönüştürmek için bir awv ve iconv komutu oluşturabilirsiniz.

Misal:

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

0

File komutuyla tek bir dosyanın kodlamasını çıkarabilirsiniz. İle bir sample.html dosyası var:

$ file sample.html 

sample.html: HTML belgesi, UTF-8 Çok uzun satırlı Unicode metin

$ file -b sample.html

HTML belgesi, UTF-8 Unicode metin, çok uzun satırlar

$ file -bi sample.html

text / html; karakter kümesi = UTF-8

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

UTF-8


1
aldığım çıktı sadece "normal dosya"
Mordechai

0

Aşağıdaki komut dosyasını kullanıyorum

  1. SRC_ENCODING ile FILTER ile eşleşen tüm dosyaları bul
  2. Bunların bir yedeğini oluşturun
  3. Bunları DST_ENCODING biçimine dönüştürün
  4. (isteğe bağlı) Yedekleri kaldırın

.

#!/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 {} \;

0

bu komutla:

for f in `find .`; do echo `file -i "$f"`; done

bir dizindeki ve alt dizinlerdeki tüm dosyaları ve ilgili kodlamayı listeleyebilirsiniz.


-2

Perl ile Encode :: Detect kullanın.


7
Kabukta nasıl kullanılacağına dair bir örnek verebilir misiniz?
Lri

Başka bir poster (@fccoelho), Python modülünü +3 alan bir çözüm olarak sağladı ve bu poster, Perl modülü dışında çok benzer bir cevap için -2 alır. Neden çifte standart ?!
Happy Green Kid Naps

4
Belki bir perl tek katlı kod örneği bu cevaba yardımcı olabilir.
vikingsteve
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.