Как найти кодировку файла через скрипт в Linux?


303

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

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

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


1
Если у вас есть представление о том, какой язык сценариев вы хотите использовать, пометьте свой вопрос названием этого языка. Это может помочь ...
MatrixFrog

1
Или, может быть, он просто пытается создать сценарий оболочки?
Шалом Креймер

1
Какой будет ответом на «какой язык сценариев».
bignose

7
Может быть, не связано с этим ответом, но совет в целом: когда вы можете описать все ваши сомнения в одном слове («кодировка», здесь), просто сделайте apropos encoding. Он ищет названия и описания всех справочных страниц. Когда я делаю это на моей машине, я вижу 3 инструментов , которые могли бы помочь мне, судя по их описаниям: chardet, chardet3, chardetect3. Затем, man chardetпрочитав man-страницу, вы узнаете, что chardetмне нужна именно эта утилита.
Джон Ред

1
Кодировка может измениться при изменении содержимого файла. Например, в vi, когда пишете простую программу на c, это возможно us-ascii, но после добавления строки китайского комментария это становится utf-8. fileможно узнать кодировку, прочитав содержимое файла и угадать.
Эрик Ван

Ответы:


419

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

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


1
Согласно справочной странице, он знает о наборе ISO 8559. Возможно, прочитайте немного менее внимательно :-)
bignose

5
Энка звучит интересно. К сожалению, обнаружение кажется очень зависимым от языка, и набор поддерживаемых языков не очень большой. Шахта (де) отсутствует :-( В любом случае классный инструмент.
er4z0r

1
Хороший пост об инструментах, таких как enca, enconv, convmv
GuruM

6
encaкажется, совершенно бесполезен для анализа файла, написанного на английском языке, но если вы что-то просматриваете на эстонском языке, это может решить все ваши проблемы. Очень полезный инструмент, который ... </
sarcasm

6
@vladkras, если в вашем файле utf-8 нет символов, отличных от ascii, то это неотличимо от ascii :)
vadipp

85
file -bi <file name>

Если вы хотите сделать это для нескольких файлов

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

Однако, если файл представляет собой файл xml с атрибутом «encoding = 'iso-8859-1» в объявлении xml, команда file скажет, что это iso-файл, даже если истинная кодировка - utf-8 ...
За

6
Почему вы используете аргумент -b? Если вы просто делаете файл -i *, он выводит угаданную кодировку для каждого файла.
Ханс-Петер Стёрр

4
Мне было любопытно и аргумент -b. Страница man говорит, что это означает "кратко"Do not prepend filenames to output lines
craq

1
Нет необходимости анализировать вывод файла, file -b --mime-encodingвыводит только кодировку charset
jesjimher

-b означает «быть кратким», что в основном означает не выводить имя файла, которое вы только что дали.
Никос

36

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

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

~> uchardet file.java 
UTF-8

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


1
Спасибо! Я не в восторге от еще большего количества пакетов, но sudo apt-get install uchardetнастолько легко, что я решил не беспокоиться об этом ...
Мудрец

Как я только что сказал в комментарии выше: uchardet ложно говорит мне, что кодировка файла была «windows-1252», хотя я явно сохранил этот файл как UTF-8. Учардет даже не говорит «с уверенностью 0.4641618497109827», что, по крайней мере, даст вам подсказку, что это говорит вам полную чушь. Файл, Enca и Encguess работали правильно.
Algoman

uchardetимеет большое преимущество по сравнению fileс тем enca, что анализирует весь файл (только что попробованный с файлом 20 ГБ), а не только начало.
Tuxayo

10

Вот пример сценария с использованием файлов -I и iconv, который работает на MacOsX. Для вашего вопроса вам нужно использовать 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

6
file -b --mime-encodingвыводит только кодировку, так что вы можете избежать обработки всех
каналов

1
Спасибо. Как указано в MacOS, это не будет работать: file -b - mime-encoding Использование: file [-bchikLNnprsvz0] [-e test] [-f namefile] [-F separator] [-m magicfiles] [-M magicfiles ] file ... file -C -m magicfiles Попробуйте `file --help 'для получения дополнительной информации.
Вольфганг Фаль

6

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

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


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

5

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

$ encguess test.txt
test.txt  US-ASCII

Я установил uchardetв Ubuntu, и он сказал мне, что мой файл был WINDOWS-1252. Я знаю, что это было неправильно, потому что я сохранил это как UTF-16 с Кейт, чтобы проверить. Однако, encguessугадайте правильно, и он был предварительно установлен в Ubuntu 19.04.
Нагев


4

С Python вы можете использовать модуль chardet: https://github.com/chardet/chardet


Несуществующий домен: feedparser.org
Rune

Что касается этого комментария, он все еще доступен на Github: github.com/dcramer/chardet
Рик Хэнлон II,

Что касается этого комментария, он находится на chardet / chardet на github. Обновленный ответ.
Квентин Прадет

chardet сообщает "None", chardet3 задыхается в первой строке файла точно так же, как мой скрипт на python.
Джоэлс Эльф

3

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

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

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

Я не говорю о буквальном переводе, таком как:

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

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


2

Я знаю, что вы заинтересованы в более общем ответе, но то, что хорошо в 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

2

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


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

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

2

В 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

0

В 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 для преобразования всего в utf8 из любой исходной кодировки, поддерживаемой 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

0

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

$ file sample.html 

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

$ file -b sample.html

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

$ file -bi sample.html

текст / html; кодировка = UTF-8

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

UTF-8


1
вывод, который я получаю, это просто "обычный файл"
Мордехай

0

Я использую следующий скрипт для

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

0

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

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

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


-2

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


7
Можете ли вы привести пример, как использовать его в оболочке?
Lri

Другой постер (@fccoelho) предоставил модуль Python в качестве решения, которое получает +3, и этот постер получает -2 для очень очень похожего ответа, за исключением того, что это для модуля Perl. Почему двойной стандарт ?!
Happy Green Kid Naps

4
Возможно, пример кода однострочного perl поможет этому ответу.
Викингстеве
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.