изменение кодировки файлов с помощью dd


Или us-ascii в utf-8 голыми руками. Те, кто хорошо знаком с кодировками, знают, что в linux есть утилита iconv, которая может менять кодировку, например, у нас есть файл «file-cp1251» в кодировке cp1251, нам надо перегнать его в utf-8. Выполняем:

iconv -f cp1251 -t utf-8 file-cp1251 > file-utf-8

Но я столкнулся с такой проблемой: есть файл на английском языке, команда file -i показывает кодировку us-ascii, iconv переделывает, но кодировка по прежнему остается us-ascii, это из-за того, что в файле нет специфических символов из таблицы utf-8, которых нет в таблице us-ascii. Если в файлик добавить такой символ, например русскую букву, он автоматически перейдет в utf-8. Вооружившись виндовозным Notepad, я увидел, что он меняет проблемный файл из us-ascii в utf-8. Что же он такое делает не изменяя при этом текст файла?

Ответ прост: он добавляет 3 спец байта в начало файла, эти байты еще называются «специальные маркеры». Если наш файл прогнать через hexdump, мы их увидим, их также видно, натравив cat -A на файл

insider@localhost:~$ file -i test
test: text/plain; charset=utf-8
insider@localhost:~$ cat test
string1
string2
insider@localhost:~$ cat -A test
M-oM-;M-?string1$
string2$
insider@localhost:~$ hexdump -C test
00000000  ef bb bf 73 74 72 69 6e  67 31 0a 73 74 72 69 6e  |...string1.strin|
00000010  67 32 0a                                          |g2.|
00000013

Как видно, эти три байта - ef bb bf. Ну а как же теперь их запихнуть в нужный нам файл без Notepad, вооружившись лишь одним terminal или console, кому как нравится?

Оказывается не так и сложно, всего лишь выполняем:

printf "\xef\xbb\xbf" | dd bs=1 count=3 oflag=append conv=notrunc of=tmpfile
dd if=test of=tmpfile oflag=append conv=notrunc
mv tmpfile test

Теперь по порядку: 1. Мы записали эти самые байты во временный файл, к сожалению в dd нет опции insert, поэтому приходится изголяться 2. Добавляем в конец временного файла с волшебными байтами наш файл test, который еще в us-ascii 3. Переименовываем временный файл в test, перезаписывая старый test

P.S. можно бы просто эти три байта добавить в конец файла test и не мучаться, только вот, если файл большой, то ничего не выйдет, байты запишутся, а кодировка останется прежней

comments powered by Disqus