Как я могу найти кодировку файла с помощью скрипта в Linux?

Мне нужно найти кодировку всех файлов, помещенных в каталог. Есть ли способ узнать используемую кодировку?

Команда file не может этого сделать.

Меня интересует кодировка ISO 8859-1. Если кодировка другая, я хочу переместить файл в другой каталог.


person Manglu    schedule 30.04.2009    source источник
comment
Если у вас есть представление о том, какой язык сценариев вы можете использовать, отметьте свой вопрос названием этого языка. Это может помочь ...   -  person MatrixFrog    schedule 30.04.2009
comment
Или, может быть, он просто пытается создать сценарий оболочки?   -  person Shalom Craimer    schedule 30.04.2009
comment
Что было бы ответом на вопрос «на каком языке сценариев».   -  person bignose    schedule 30.04.2009
comment
Извините, я не ясно выразился. Я смотрел на создание сценария оболочки, как упоминал скраймер. Отныне буду поясняться. Спасибо, Manglu   -  person Manglu    schedule 01.05.2009
comment
Может быть, это не связано с этим ответом, но совет в целом: когда вы можете описать все свои сомнения одним словом (кодировка, здесь), просто сделайте apropos encoding. Он ищет заголовки и описания всех страниц руководства. Когда я делаю это на своей машине, я вижу 3 инструмента, которые могут мне помочь, судя по их описаниям: chardet, chardet3, chardetect3. Затем, выполнив man chardet и прочитав справочную страницу, я узнаю, что chardet - это как раз та утилита, которая мне нужна.   -  person John Red    schedule 18.05.2016
comment
Кодировка может измениться при изменении содержимого файла. например, в vi, когда вы пишете простую программу на c, это, вероятно, us-ascii, но после добавления строки китайского комментария оно становится utf-8. file может определить кодировку, прочитав содержимое файла и угадав.   -  person user218867    schedule 03.09.2016
comment
Я только что запустил chardetect, chardet3, chardetect3 и uchardet для файла, который я явно сохранил как UTF-8. Мне постоянно говорят, что кодировка была windows-1252 с уверенностью 0.4641618497109827. file и enca правильно говорят мне, что это UTF-8. Возможно, вам нужно указать chardet, какую кодировку попробовать, но я не мог понять, как это сделать, потому что вывод --help chardet - это мусор.   -  person Algoman    schedule 03.05.2018


Ответы (17)


Похоже, вы ищете enca. Он может угадывать и даже конвертировать между кодировками. Просто посмотрите справочную страницу.

В противном случае используйте file -i (Linux) или file -I (OS X). Это выведет информацию о типе MIME для файла, которая также будет включать кодировку набора символов. Я тоже нашел для него справочную страницу :)

person Shalom Craimer    schedule 30.04.2009
comment
Похоже, что это не поддерживает 8859-1 (просто от беглого взгляда на эту страницу руководства). - person paxdiablo; 30.04.2009
comment
Согласно странице руководства, он знает о наборе ISO 8559. Возможно, прочтите чуть менее бегло :-) - person bignose; 30.04.2009
comment
8859-2,4,5,13 и 16, без упоминания 8859-1. Символы выше 0x7f сильно различаются между вариантами -1 и -2. - person paxdiablo; 30.04.2009
comment
Привет, я работаю в среде AIX, и похоже, что enca в этой среде не существует. Спасибо, Manglu - person Manglu; 01.05.2009
comment
Энка звучит интересно. К сожалению, обнаружение, похоже, очень зависит от языка, а набор поддерживаемых языков невелик. Mine (de) отсутствует :-( Во всяком случае крутой инструмент. - person er4z0r; 05.04.2010
comment
Он не поддерживает японские кодировки. Запуск enca --list languages показывает в основном русскую и восточноевропейскую (плюс несколько китайских) кодировок. Ну что ж! Тогда снова в Google. - person GuruM; 19.06.2012
comment
Хорошая публикация об инструментах, таких как enca, enconv, convmv - person GuruM; 19.06.2012
comment
enca кажется совершенно бесполезным для анализа файла, написанного на английском языке, но если вы случайно посмотрите что-то на эстонском, это может решить все ваши проблемы. Очень полезный инструмент, который ... ‹/sarcasm› - person cbmanica; 17.04.2013
comment
Используйте file -b --mime-encoding YOURFILE только для печати кодировки - person Ivan Chau; 04.09.2013
comment
Я использую эту команду, чтобы проверить, является ли это utf-8: if file --brief --mime-encoding YOURFILE | grep -q "utf-8"; then echo "I am utf-8 encoded"; else echo "I am different"; fi Спасибо @IvanChau - person Petr Újezdský; 30.07.2015
comment
мой index.php - это 100% utf-8, но file -i показывает us-ascii - person vladkras; 21.11.2016
comment
@vladkras, если в вашем файле utf-8 нет символов, отличных от ascii, то он неотличим от ascii :) - person vadipp; 02.03.2017
comment
@vadipp, даже если я создам новый файл utf-8 с 'abc' внутри, он показывает myfile.txt: text/plain; charset=us-ascii - person vladkras; 02.03.2017
comment
@vladkras, вот что я сказал: a, b и c - все символы ascii, и их представление utf-8 такое же, как ascii. Если вам интересно, прочтите, как работает кодировка utf-8. - person vadipp; 02.03.2017
comment
@vadipp пропустил двойной no в вашем комментарии, в любом случае phpstorm обнаруживает эти файлы, такие как не-utf8, а file -i показывает ascii - person vladkras; 03.03.2017

file -bi <file name>

Если вы хотите сделать это для группы файлов

for f in `find | egrep -v Eliminate`; do echo "$f" ' -- ' `file -bi "$f"` ; done
person madu    schedule 27.07.2012
comment
Однако, если файл является файлом xml с атрибутом encoding = 'iso-8859-1' в объявлении xml, команда file скажет, что это файл iso, даже если истинная кодировка - utf-8 ... - person Per; 11.09.2012
comment
Почему вы используете аргумент -b? Если вы просто выполните file -i *, он выведет предполагаемую кодировку для каждого файла. - person Hans-Peter Störr; 26.06.2013
comment
Мне тоже был любопытен аргумент -b. На странице руководства сказано, что это означает краткое Do not prepend filenames to output lines - person craq; 12.01.2016
comment
Нет необходимости анализировать вывод файла, file -b --mime-encoding выводит только кодировку кодировки - person jesjimher; 18.04.2018
comment
все, что я получаю, это обычный файл в качестве вывода при выполнении этого - person Robert Sinclair; 28.12.2019

uchardet - библиотека детектора кодирования, перенесенная из Mozilla.

Использование:

~> uchardet file.java
UTF-8

Различные дистрибутивы Linux (Debian, Ubuntu, openSUSE, Pacman и т. д.) предоставляют двоичные файлы.

person qwert2003    schedule 29.12.2015
comment
Спасибо! Я не в восторге от новых пакетов, но sudo apt-get install uchardet это настолько просто, что я решил не беспокоиться об этом ... - person sage; 10.03.2016
comment
Как я только что сказал в комментарии выше: uchardet ложно сообщает мне, что кодировка файла была windows-1252, хотя я явно сохранил этот файл как UTF-8. uchardet даже не говорит с уверенностью 0,4641618497109827, что, по крайней мере, даст вам намек на то, что он говорит вам полную ерунду. file, enca и encguess работали правильно. - person Algoman; 03.05.2018
comment
uchardet имеет большое преимущество перед file и enca в том, что он анализирует весь файл (только что попробовал с файлом 20 ГБ), а не только начало. - person tuxayo; 20.01.2020

Вот пример сценария с использованием file -I и iconv, который работает в Mac OS X.

Для вашего вопроса вам необходимо использовать mv вместо 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
person Wolfgang Fahl    schedule 08.02.2016
comment
file -b --mime-encoding выводит только кодировку, поэтому вы можете избежать обработки конвейера - person jesjimher; 18.04.2018
comment
Спасибо. Как указывалось в MacOS, это не сработает: file -b --mime-encoding Использование: file [-bchikLNnprsvz0] [-e test] [-f namefile] [-F separator] [-m magicfiles] [-M magicfiles ] файл ... файл -C -m magicfiles Для получения дополнительной информации попробуйте `file --help '. - person Wolfgang Fahl; 19.04.2018

В Debian вы также можете использовать: encguess:

$ encguess test.txt
test.txt  US-ASCII
person not2qubit    schedule 21.02.2018
comment
Я установил uchardet в Ubuntu, и он сказал мне, что мой файл был WINDOWS-1252. Я знаю, что это было неправильно, потому что я сохранил его как UTF-16 с Кейт, чтобы проверить. Однако encguess угадайте правильно, и он был предустановлен в Ubuntu 19.04. - person Nagev; 11.06.2019
comment
Отлично, работает отлично. Я добавляю один небольшой совет: в ubuntu / debian enguess он находится внутри пакета perl. Если у вас установлен этот пакет, но он не работает, попробуйте /usr/bin/encguess - person NetVicious; 18.06.2021

Чтобы преобразовать кодировку из ISO 8859-1 в ASCII:

iconv -f ISO_8859-1 -t ASCII filename.txt
person fimbulwinter    schedule 18.02.2019

Действительно сложно определить, соответствует ли это ISO 8859-1. Если у вас есть текст, состоящий только из 7-битных символов, это также может быть ISO 8859-1, но вы не знаете. Если у вас есть 8-битные символы, тогда символы верхнего региона также существуют в порядковых кодировках. Поэтому вам придется использовать словарь, чтобы лучше угадать, какое это слово, и определить оттуда, какая буква это должна быть. Наконец, если вы обнаружите, что это может быть UTF-8, вы уверены, что это не ISO 8859-1.

Кодирование - одна из самых сложных задач, потому что никогда не знаешь, что тебе ничего не говорит.

person Norbert Hartl    schedule 30.04.2009
comment
Может помочь попытка перебора. Следующая команда попытается преобразовать все форматы ecncoding с именами, начинающимися с WIN или ISO, в UTF8. Затем нужно будет вручную проверить вывод в поисках подсказки в правильной кодировке. Конечно, вы можете изменить отфильтрованные форматы, заменив ISO или WIN на что-то подходящее, или удалить фильтр, удалив команду grep. для i в $ (iconv -l | tail -n +2 | grep (^ ISO \ | ^ WIN) | sed -e 's / \ / \ ///'); сделать echo $ i; iconv -f $ i -t UTF8 santos; Выполнено; - person ndvo; 17.01.2020

В Python вы можете использовать модуль chardet.

person fccoelho    schedule 18.07.2011
comment
chardet сообщает None, chardet3 блокирует первую строку файла точно так же, как и мой скрипт python. - person Joels Elf; 30.05.2016

Это не то, что вы можете сделать надежным способом. Одна из возможностей - проверить каждый символ в файле, чтобы убедиться, что он не содержит никаких символов в диапазонах 0x00 - 0x1f или 0x7f -0x9f, но, как я уже сказал, это может быть верно для любого количества файлов, включая хотя бы один другой вариант ISO 8859.

Другая возможность - поискать определенные слова в файле на всех поддерживаемых языках и посмотреть, сможете ли вы их найти.

Так, например, найдите эквивалент английского и, но, to, of и т. Д. На всех поддерживаемых языках ISO 8859-1 и посмотрите, есть ли у них большое количество вхождений в файле.

Я не говорю о дословном переводе, например:

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

хотя это возможно. Я говорю об общих словах в целевом языке (насколько я знаю, в исландском нет слова для и - вам, вероятно, придется использовать их слово для обозначения рыбы [извините, это немного стереотипно. Я не имел в виду никакого оскорбления, просто иллюстрирую точку]).

person paxdiablo    schedule 30.04.2009

Я знаю, что вас интересует более общий ответ, но то, что хорошо в ASCII, обычно хорошо в других кодировках. Вот однострочник Python, чтобы определить, является ли стандартный ввод ASCII. (Я почти уверен, что это работает в Python 2, но я тестировал его только на 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
person wkschwartz    schedule 30.05.2012

Если вы говорите о файлах XML (ISO-8859-1), объявление XML внутри них указывает кодировку: <?xml version="1.0" encoding="ISO-8859-1" ?> Итак, вы можете использовать регулярные выражения (например, с Perl) для проверки каждого файла на наличие такой спецификации.

Дополнительную информацию можно найти здесь: Как определить кодировку текстового файла.

person evgeny9    schedule 27.01.2012
comment
ну, эта строка может быть скопирована и вставлена ​​кем-то, кто не знает, какую кодировку он использует. - person Algoman; 03.05.2018
comment
Предупреждение: ничего в объявлении вверху не гарантирует, что файл ДЕЙСТВИТЕЛЬНО закодирован таким образом. Если вы действительно заботитесь о кодировке, вам нужно проверить ее самостоятельно. - person Jazzepi; 19.08.2019

В PHP вы можете проверить это, как показано ниже:

Явное указание списка кодировок:

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

Более точные mb_list_encodings:

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

Здесь, в первом примере, вы можете видеть, что я использовал список кодировок (определение порядка списка), которые могут совпадать. Чтобы получить более точный результат, вы можете использовать все возможные кодировки с помощью: mb_list_encodings ()

Обратите внимание, что для функций mb_ * требуется php-mbstring:

apt-get install php-mbstring
person Mohamed23gharbi    schedule 12.07.2019

Я использую следующий сценарий, чтобы

  1. Найти все файлы, соответствующие FILTER с SRC_ENCODING
  2. Создайте их резервную копию
  3. Преобразуйте их в DST_ENCODING
  4. (необязательно) Удалите резервные копии

 

#!/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 {} \;
person Matyas    schedule 05.09.2018

С помощью этой команды:

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

вы можете перечислить все файлы в каталоге и подкаталогах и в соответствующей кодировке.

Если в имени файла есть пробел, используйте:

IFS=$'\n'
for f in `find .`; do echo `file -i "$f"`; done

Помните, что это изменит ваш текущий интерпретатор сеанса Bash для пробелов.

person danilo    schedule 28.08.2019
comment
привет, сценарий не работает, когда в имени файла есть пробел, как бы это исправить? - person jerry; 06.03.2021
comment
да, вы должны использовать IFS (внутренний разделитель полей) тип IFS=$'\n' перед использованием скрипта: askubuntu.com/a/344418/734218 - person danilo; 06.03.2021

Вы можете извлечь кодировку одного файла с помощью команды file. У меня есть файл sample.html с:

$ file sample.html 

sample.html: HTML-документ, текст Unicode UTF-8 с очень длинными строками.

$ file -b sample.html

Документ HTML, текст Unicode UTF-8 с очень длинными строками

$ file -bi sample.html

текст / html; charset = utf-8

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

utf-8

person Daniel Faure    schedule 05.04.2018
comment
вывод, который я получаю, - это просто обычный файл - person Mordechai; 11.05.2018

В Cygwin, похоже, у меня это работает:

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

Пример:

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

Вы можете передать это в AWK и создать команду iconv для преобразования всего в UTF-8 из любая исходная кодировка, поддерживаемая iconv.

Пример:

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
person skeetastax    schedule 27.05.2017

В Perl используйте Encode :: Detect.

person manu_v    schedule 23.01.2012
comment
Можете привести пример, как его использовать в оболочке? - person Lri; 01.05.2012
comment
Другой плакат (@fccoelho) предоставил модуль Python в качестве решения, которое получает +3, а этот плакат получает -2 за очень очень похожий ответ, за исключением того, что он предназначен для модуля Perl. Почему двойной стандарт ?! - person Happy Green Kid Naps; 09.09.2016
comment
Может быть, в этом ответе поможет пример кода однострочника perl. - person vikingsteve; 20.10.2016