Часто бывает, что файлы упакованы в архив не в той кодировке. Сами файлы можно с лёгкостью перекодировать в нормальный (для нас) вид, но что делать с именами? Вот например я скачал множество интересной документации с сайта http://wiki.kryukov.biz/, однако автор уж очень любит называть файлы по-русски, да ещё со всякими двоеточиями и пробелами (чего делать НЕ следует). Возможно конечно это и не автор, а его викопедичный движок, но меня это конечно всё равно не радует.
Этот рисунок хотя и похож на предыдущий случай (напомню, там я не смог восстановить имена, и переименовал файлы по имени их inode), однако довольно сильно отличается: Во первых здесь нет вопросительных знаков, а значит все символы сохранились, и их можно восстановить. Во вторых тут есть ещё и проценты, про них после. Выполним:
$ ls | iconv -f utf-8 -c Сл%83жебна%8F:SpecialPages Сл%83жебна%8F:UserLogin Сл%83жебна%8F:WhatLinksHere/ Создание_кл%8E%87ей_и_%81е%80%82и%84ика%82ов Спе%86иал%8Cн%8Bе_п%80ава С%81%8Bлки С%82анда%80%82н%8Bй_ввод,_в%8Bвод_и_в%8Bвод_о%88ибки С%82%80%83к%82%83%80и%80ованн%8Bе_%82ек%81%82ов%8Bе_%84айл%8B Тек%81%82ов%8Bе_%80едак%82о%80%8B Тип%8B_%84айлов Тип%8B_%84айлов%8B%85_%81и%81%82ем У%81%82ановка_Cyrus-imapd_в_Slackware_Linux У%81%82ановка_Postfix_в_Slackware_Linux У%81%82ановка_Postfix_из_и%81%85одн%8B%85_кодов У%87а%81%82ник:Artur У%87а%81%82ник:Frantony У%87а%81%82ник:Svasilie Файл:Book-02-1.png Файл:Flag_ru.jpg Файл:Mail-schema.jpg Файл:Postfix_arch.gif Файл_group
Вот, стало всё более читаемо, но остались некоторые непонятки. Оказывается, уже в изначальном каталоге некоторые русские символы сменились на код %XX, наверное это произошло при сохранении страницы программой wget. Как-бы там не было, мы можем вернуть символы обратно sed-командой s.
Другая проблема заключается в том, что не все команды и не всегда принимают такие кривые параметры, например если передать имя из буфера sed прямо в команду, а потом её выполнить, файл просто не будет найден. Необходимо пойти более прямым путём: я передавал имя прямо внутри утилиты find с опцией -exec. Думаю это самый надёжный путь.
Сначала найдём все файлы и их inode командой
$ find . ! -path "./ren/*" -printf "%i %p\n"
Я решил сделать копию нашего каталога (.) внутри него-же в подкаталоге ./ren/, потому мне потребовалось его исключить. Затем я просто вывожу в поток кривые имена и inode файлов.
Далее поток с битыми именами поступает в sed-скрипт:
Пример 4.16. Переименование файлов командой iconv.
#!/bin/sed -rf s/.*/echo -e '&' | iconv -f utf-8 -c/e s/%80/р/g s/%81/с/g s/%82/т/g s/%83/у/g s/%84/ф/g s/%85/х/g s/%86/ц/g s/%87/ч/g s/%88/ш/g s/%89/щ/g s/%8A/ъ/ig s/%8B/ы/ig s/%8C/ь/ig s/%8D/э/ig s/%8E/ю/ig s/%8F/я/ig s/%90/А/g s/%91/Б/g s/%92/В/g s/%93/Г/g s/%94/Д/g s/%95/Е/g s/%96/Ж/g s/%97/З/g s/%98/И/g s/%99/Й/g s/%9A/К/ig s/%9B/Л/ig s/%9C/М/ig s/%9D/Н/ig s/%9E/О/ig s/%9F/П/ig s/\\/\\\\/g s/'/\\'/g s|^([0-9]+) \./(.*)|find -inum \1 -exec cp -v -r {} 'ren/\2' \\;|e
Кстати, получившиеся копия всё равно не работает, точнее смотреть её можно, но по ссылкам не попрыгать. Причина в самих ссылках:
href="/wiki/%D0%9E%D0%B3%D0%BB%D0%B0%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5"
Такие ссылки можно исправить следующим скриптом:
#!/bin/sed -rf s/charset=UTF-8/charset=KOI8-R/ /href="[^"]*%D[01]%[89A-F][0-9A-F][^"]*"/ { s//\n&\n/ h s/.*\n([^\n]+)\n.*/\1/ s/%D([01])%([89A-F][0-9A-F])/\\xD\1\\x\2/g s/.*/echo -e \x27&\x27/e s|^href="/wiki/|href="| G s/(.*)\n(.*)\n(.*)\n(.*)/\2\1\4|/ }
После чего весь файл нужно сконвертировать в KOI8-R.
Свой тестовый комп я перевёл с Slacky 10 на 13ю. Кроме разнообразных красивостей и полезностей вроде HALа, я получил ещё и кодировку UTF-8. Не слишком понятно, зафига она вообще нужна (учитывая, что я уже слишком старый, что-бы учить китайский :-) ), но это всё привело к резкому уменьшению скорости работы с текстами... Впрочем, это всё легко лечится отключением UTF (например можно приравнять $LC_ALL в "C").
Другая проблема - это то, что старые файлы с русскими именами теперь не читаются:
Решить эту проблему не так просто, как решается проблема с кодировкой на внешних носителях.
mount -t vfat -o iocharset=utf8,codepage=866 /dev/sda1 /mnt/usb
Дело в том, что при монтировании EXT3 никакой ошибки не происходит - такие имена вполне допустимы для наших ФС.
Именно по этому файлы приходится переименовывать. Я сделал это следующим скриптом (перед его применением выполните export LC_ALL=C, иначе sed не сможет обработать несимволы, которыми являются русские буквы в кодировке KOI8-R). Скрипт запускается так:
find КАТАЛОГ | ren-koi8.sed
Пример 4.17. Переименование файлов командой iconv. (для каталогов и файлов).
#!/bin/sed -rnf # export LC_ALL=C # сохранение оригинального имени файла h # конвертирование в UTF-8 s/'/'"'"'/g s/.*/echo -e '&' | iconv -f koi8-r -t utf-8/ep H # проверка. является-ли файл каталогом? g s/\n.*// s/'/'"'"'/g s/.*/test -d '&'; echo $?/e /^0$/{ # это каталог g s/.*\n// s/'/'"'"'/g s~.*~mkdir -vp 't/&' >/dev/stderr; echo $?~e /^0$/! b error b } # это файл g s/'/'"'"'/g s~(.*)\n(.*)~cp -v '\1' 't/\2' >/dev/stderr; echo $?~e /^0$/! { :error s/.*/Erorr code &/p q 77 }
Вы можете обсудить этот документ на форуме. Текст предоставляется по лицензии GNU Free Documentation License (Перевод лицензии GFDL).
Вы можете пожертвовать небольшую сумму яндекс-денег на счёт 41001666004238 для оплаты хостинга, интернета, и прочего. Это конечно добровольно, однако это намного улучшит данный документ (у меня будет больше времени для его улучшения). На самом деле, проект часто находится на грани закрытия, ибо никаких денег никогда не приносил, и приносить не будет. Вы можете мне помочь. Спасибо.