Как узнать кодировку файла в Unix с помощью скрипта(ов)

StackOverflow https://stackoverflow.com/questions/805418

  •  03-07-2019
  •  | 
  •  

Вопрос

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

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

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

Это было полезно?

Решение

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

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

Другие советы

file -bi <file name>

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

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

учардет — Библиотека детектора кодирования, портированная из Mozilla.

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

~> uchardet file.java 
UTF-8

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

Вот пример сценария с использованием файла -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

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

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

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

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

$ encguess test.txt
test.txt  US-ASCII

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

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

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

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

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

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

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

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

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

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

В 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

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

$ file sample.html 

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

$ file -b sample.html

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

$ file -bi sample.html

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

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

utf-8

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top