iconv
Перекодировка текста между UTF-8, CP1251, KOI8-R и другими; транслитерация и как определить кодировку
iconv переводит текст из одной кодировки в другую: например, файл из Windows в CP1251 — в UTF-8, чтобы вместо «кракозябр» появилась кириллица. Сама команда кодировку не угадывает — исходную нужно знать или определить заранее.
Синтаксис
iconv -f ИЗ -t В [опции] [файл…]
Без файла читает stdin, результат пишет в stdout. Если не указать -f или -t, берётся кодировка текущей локали.
Опции
| Опция | Что делает |
|---|---|
-f КОДИРОВКА | исходная кодировка (--from-code) |
-t КОДИРОВКА | целевая кодировка (--to-code) |
-l | список всех известных кодировок и их псевдонимов |
-o файл | записать результат в файл (можно тот же, что и входной) |
-c | молча выбрасывать символы, которых нет в целевой кодировке; код выхода 0 |
-s | не печатать предупреждения |
--verbose | печатать имена обрабатываемых файлов |
Суффиксы целевой кодировки
| Суффикс | Что делает с символом, которого нет в целевой кодировке |
|---|---|
| (нет) | останавливается: illegal input sequence at position N, код 1 |
//TRANSLIT | заменяет похожим: é → e, – → -, кириллицу — латиницей; если замены нет — ? |
//IGNORE | выбрасывает символ, но в конце всё равно сообщает об ошибке и возвращает 1 |
Частые кодировки
| Имя | Где встречается |
|---|---|
UTF-8 | стандарт в Linux, вебе, JSON |
CP1251 (WINDOWS-1251) | кириллица в старых файлах из Windows |
KOI8-R | кириллица в старых Unix-системах и письмах |
CP866 | кириллица в DOS и консоли Windows |
ISO-8859-1 (LATIN1) | западноевропейские языки |
UTF-16LE / UTF-16 | файлы из Windows-программ; UTF-16 пишет BOM в начале |
ASCII | только латиница, цифры и знаки — 128 символов |
Имена нечувствительны к регистру, дефис часто можно опустить: cp1251, utf8 тоже работают.
Примеры
# файл из Windows в UTF-8
iconv -f CP1251 -t UTF-8 report.txt > report.utf8.txt
# наоборот: подготовить файл для старой Windows-программы
iconv -f UTF-8 -t CP1251 data.csv > data-win.csv
# перекодировать файл «на месте» через -o
iconv -f CP1251 -t UTF-8 -o notes.txt notes.txt
# есть ли кодировка в списке
iconv -l | grep -i 1251
# латиница вместо диакритики и кириллицы; результат зависит от локали
echo 'Café – naïve' | LC_ALL=C.UTF-8 iconv -f UTF-8 -t ASCII//TRANSLIT
# выбросить всё, что не влезает в ASCII
echo 'Café' | iconv -c -f UTF-8 -t ASCII
# проверить, что файл — корректный UTF-8: код выхода 0 — да
iconv -f UTF-8 -t UTF-8 file.txt > /dev/null && echo 'валидный UTF-8'
# перекодировать все .txt в каталоге
for f in *.txt; do iconv -f CP1251 -t UTF-8 -o "$f" "$f"; done
Как определить кодировку
file -i report.txt
# report.txt: text/plain; charset=utf-8
file -b --mime-encoding report.txt
Утилиты file может не быть в минимальной системе (её ставят пакетом file). file лишь угадывает: us-ascii и utf-8 определяет надёжно, а однобайтные кириллические кодировки обычно показывает как iso-8859-1 или unknown-8bit. Тогда пробуй варианты: iconv -f CP1251 -t UTF-8 файл | head и смотри, где текст читается.
Подводные камни
> тот же файлего обнуляет.iconv … f.txt > f.txt— оболочка очистит файл до запускаiconv. Используй-o f.txtили временный файл.- Неверная
-fне всегда даёт ошибку. Любые байты — допустимый текст вCP1251илиKOI8-R, поэтому перекодировка из неправильной кодировки пройдёт «успешно» и выдаст бессмыслицу вродеоПХБЕР. Проверяй результат глазами. - Повторный запуск портит файл. Перекодировка уже сконвертированного файла ещё раз (
CP1251 → UTF-8над UTF-8) пройдёт без ошибок и дастПриветвместоПривет. В циклах по файлам пиши результат в новый каталог или проверяй файл перед конвертацией. //TRANSLITзависит от локали. В локалиC/POSIXмногие символы превращаются в?. Запускай сLC_ALL=C.UTF-8или другой UTF-8-локалью.//IGNOREвозвращает1. Даже выбросив всё лишнее,iconvсообщает об ошибке. Для скриптов надёжнее-c.- BOM. Файлы из Windows в UTF-8 иногда начинаются с байтов
EF BB BF.iconv -f UTF-8 -t UTF-8их не убирает; они ломают первую строку CSV и шебанг скрипта. Удалить можно черезsed '1s/^\xEF\xBB\xBF//'. - Переводы строк
\r\n— это не кодировка,iconvих не меняет. Для них нужныtr -d '\r'илиdos2unix.