В поддержке legacy-кода и обновлении скритов нередко возникает задача их перекодирования в utf-8
. Это хорошо выполняется стандарной утилитой iconv
, вот её использование для одного файла:
iconv -f cp1251 -t utf8 orig-in-cp1251.php -o out-in-utf8.php
При этом не удастся указать одинаковое входное и выходное названия: iconv начнёт писать до получения входа и получится файл нулевой длины. В этом случае станартный вывод полезно «замочить в губке» с помощью sponge
. Сделаем однострочный скрипт, который делает всё сразу, он понадобится далее (назовём его to-utf8.sh
):
#!/bin/sh /usr/bin/iconv -f cp1251 -t utf8 "$1" | sponge "$1"
В качестве единственного аргумента он берет имя файла и рекодит его полностью.
Обычно требуется сконвертить все файлы определённого расширения в целой директории. Подключаем ещё find
:
find /here-is-my-files/ -type f -iname "*.js" -exec to-utf8.sh "{}" \;
На часть файлов iconv
может ругнуться в STDERR
и эти файлы целесообразно проверить/перекодировать вручную.
Ещё более сложный (и достаточно частый) случай, когда есть файлы в разных кодировках и их необходимо перевести в одну. iconv
в этом случае может сконвертировать ещё раз и испортить файл. То есть, нужно распознать исходную кодировку и рекодить только «не те» файлы.
Тогда помогает самый лучший вариант: утилиты enca/enconv
. Из них первая только распознаёт кодировку, а вторая ещё и перекодирует.Интерфейс enconv
до безобразия простой: в случае одного параметра она перекодирует файл из исходной (ЛЮБОЙ распознанной!) кодировки в ту, что указана в locale
. Кодировку можно указать явно, тогда вся задача решается одной строкой
find /here-is-my-files/ -type f -iname "*.js" -exec enca "{}" \;
Для улучшения точности язык также можно «подсказать», с помощью параметра (-L ru
).
Последний, enca
-способ, похоже самый оптимальный для большинства задач.