- проблемы с кодировкой в названии файлов
- Понимание кодировки имени файла Unix
- Имена файлов хранятся в виде символов
- Имена файлов хранятся в виде двоичных объектов
- HowTo: Check and Change File Encoding In Linux
- Check a File’s Encoding
- Change a File’s Encoding
- List All Charsets
- 8 Replies to “HowTo: Check and Change File Encoding In Linux”
проблемы с кодировкой в названии файлов
Перенес файлы с одного сервера на другой. Некоторые символы в названиях файлов стали отображаться как квадраты, например «№». Причем с этими файлами нельзя ничего сделать через файлменеджер, ни удалить, ни переименовать, т.к. пишет что файл не сущетвует (а его видно).
Вопрос в том, что сделать, чтобы названии таких файлов корректно отображались все символы?
Можно сделать по номеру inode через find. Вменяемого решения проблемы в целом не могу сказать, не ясно что там приключилось в процессе переноса — как переносили файлы, какая ОС\локали там и там?
Включить однобайтную локаль. Например, KOI8-R. Тогда отдельные байты распарсятся без ошибок. Хоть и смысла в итоговых именах может быть никакого. Но, зато с файлами можно будет легко проводить операции — переименовывать, удалять. и т.д.
Переносил rsync, с ubuntu 12.04 (cp1251) на ubuntu 14.04(utf8). С локального компьютера, где стоит ubuntu 14.04, подключаюсь через файловый менеджер к старому серверу и тоже вижу квадраты. Т.е. проблема возникла не во время переноса
подскажите, пожалуйста, что для этого нужно)
Если имена файлов уже в cp1251, то выставить лучше cp1251. Для этого надо выполнить
После этого, кстати, можно будет пройтись по файлам скриптом, автоматически переименовывая их в UTF-8. Например, таким:
/cp1251toutf8. Тогда можно просто перейти в директорию с файлами и выполнить
После переименования можно будет вернуть обратно UTF-8.
не хотелось бы выставлять cp1251. в названии файлов, думаю кириллицы нет, только с символами типа «№» проблемы почему то(
rsync не меняет кодировку имен файлов, как записано, так и сохраняет. Вот и остались в однобайтной CP1251. Для перекодирования можно использовать утилиту convmv:
Потому, что этих символов нет в ASCII. Соответственно, для однобайтной cp1251 их коды больше чем 127. Что для парсера юникода включает _последовательности_ из ряда байтов. При этом, поскольку, эти байты никто не подбирал, чтобы они создавали корректные для UTF-8 последовательности, местами получаются невалидные для UTF-8 последовательности (да, в UTF-8 есть такое). И парсеры юникода ломаются.
Для парсеров же однобайтных кодировок любые последовательности байт валидны, поскольку каждый отдельный байт воспринимается как отдельный указатель на один из 256-ти символов.
юзал без ключа «—notest», сам затупил. Очень много нервных клеток вы мне съэкономили)
Источник
Понимание кодировки имени файла Unix
Мне трудно понять, как работает кодировка имени файла. На unix.SE я нахожу противоречивые объяснения.
Имена файлов хранятся в виде символов
[…] Как вы упоминаете в своем вопросе, имя файла UNIX — это просто последовательность символов; ядро ничего не знает о кодировке, которая полностью является концепцией пользовательского пространства (т.е. уровня приложения).
Если имена файлов хранятся в виде символов, должна использоваться какая-то кодировка, поскольку в конечном итоге имя файла должно заканчиваться последовательностью битов или байтов на диске. Если пользователь может выбрать любую кодировку для сопоставления символов с последовательностью байтов, которая подается в ядро, можно создать любую последовательность байтов для действительного имени файла.
Предположим следующее: пользователь использует случайную кодировку X , которая переводит файл foo в последовательность байтов α и сохраняет его на диск. Другой пользователь использует кодирующий Y . В этой кодировке α переводится как / , что не допускается в качестве имени файла. Однако для первого пользователя файл действителен.
Я предполагаю, что этот сценарий не может произойти.
Имена файлов хранятся в виде двоичных объектов
Как отмечают другие, на самом деле нет ответа на это: имена файлов и пути не имеют кодировки; ОС работает только с последовательностью байтов. Отдельные приложения могут по своему усмотрению интерпретировать их как кодируемые, но это варьируется.
Если система не работает с символами, как можно запретить использование определенных символов (например, / или NULL ) в именах файлов? Там нет понятия / без кодировки.
Объяснение может состоять в том, что файловая система может хранить имена файлов, содержащие любой символ, и только пользовательские программы, принимающие во внимание кодировку, будут подавлять имена файлов, содержащие недопустимые символы. Это, в свою очередь, означает, что файловые системы и ядро могут без каких-либо затруднений обрабатывать имена файлов, содержащие / .
Я также предполагаю, что это неправильно.
Где происходит кодирование и где накладывается ограничение, запрещающее использование определенных символов?
Краткий ответ: ограничения, налагаемые в ядре Unix / Linux / BSD, namei() функция. Кодирование происходит в программах уровня пользователя, таких как xterm , firefox или ls .
Я думаю, что вы начинаете с неправильных посылок. Имя файла в Unix — это строка байтов с произвольными значениями. Несколько значений 0x0 (ASCII Nul) и 0x2f (ASCII ‘/’) просто недопустимы, ни как часть многобайтовой кодировки символов, ни как что-либо еще. «Байт» может содержать число, представляющее символ (в ASCII и некоторых других кодировках), но «символ» может требовать более 1 байта (например, кодовые точки выше 0x7f в представлении Unicode в UTF-8).
Эти ограничения вытекают из соглашений о печати имен файлов и набора символов ASCII. Исходные Unix-ы использовали ASCII ‘/’ (численно 0x2f) байты для разделения частей частично или полностью квалифицированного пути (например, ‘/ usr / bin / cat’ содержит фрагменты «usr», «bin» и «cat») , Оригинальные Unixes использовали ASCII Nul для завершения строк. Помимо этих двух значений, байты в именах файлов могут принимать любые другие значения. Эхо этого можно увидеть в кодировке UTF-8 для Unicode. Печатные символы ASCII, включая «/», занимают в UTF-8 только один байт. UTF-8 для кодовых точек выше не содержит байтов с нулевым значением, кроме управляющего символа Nul. UTF-8 был изобретен для Plan-9, претендента на трон Unix.
В более ранних версиях Unix (и, похоже, в Linux) была namei() функция, которая просто просматривает пути по байту за раз и разбивает пути на части по 0x2F-значным байтам, останавливаясь на нулевом значении. namei() является частью ядра Unix / Linux / BSD, поэтому здесь применяются исключительные байтовые значения.
Обратите внимание, что до сих пор я говорил о значениях байтов, а не символов. namei() не применяет семантику символов в байтах. Это зависит от программ уровня пользователя, например ls , которые могут сортировать имена файлов по байтовым значениям или символьным значениям. xterm решает, какие пиксели загораться для имен файлов, основываясь на кодировке символов. Если вы не скажете, xterm что у вас есть имена файлов в кодировке UTF-8, вы увидите много тарабарщины, когда вызовете его. Если vim он не скомпилирован для обнаружения кодировок UTF-8 (или чего-либо другого, UTF-16, UTF-32), вы увидите много бреда при открытии «текстового файла», содержащего символы в кодировке UTF-8.
Дело в том, что ядру все равно, как приложения интерпретируют данные, которые ему даны как имя файла.
Давайте представим, что у меня есть приложение на C, которое работает исключительно со строками UTF-16. И я ввожу через правильно настроенный метод ввода символ ∯ (Unicode 0x222F) в подсказку / диалог «Сохранить как».
Если приложение не выполняет какую-либо форму перевода и отправляет ее в простой старой строке C ( char* ), скажем, fopen в режиме записи, ядро не увидит ∯ или даже не попытается это представить. Он будет видеть два char s, одно за другим, со значениями 0x22 0x2F (при условии, что 8-битные символы отсутствуют, а в библиотеке C нет ничего смешного ).
То есть, с точки зрения ядра, допустимый char ( » ), за которым следует / (ASCII 0x2F). fopen вернется EISDIR (т. е. «это похоже на каталог, и вы запросили режим записи!»).
Если бы я ввел ∮ (Unicode 0x222E ), ядро увидело бы два точных символа и создало бы файл, который, как видно из приложения, говорящего на ASCII, был бы назван «. .
Если бы я ввел a в приложение имя файла, и приложение передало его в UTF-16 ядру, ядро прочитало бы 0x00 0x61 и даже не приняло это во внимание 0x61 , потому 0x00 что строка уже заканчивает строку, насколько она есть. обеспокоен. Сообщение об ошибке будет таким же, как и для пустого имени файла ( ENOENT я считаю).
Таким образом, ядро действительно воспринимает данные как блоб. Это поток char с. Недопустимые «символы» в выбранной вами кодировке пользовательского пространства — это те, которые генерируют 0x00 или 0x2F («ноль» и / ) в своем двоичном объекте (двоичное представление, которое передается ядру).
Источник
HowTo: Check and Change File Encoding In Linux
The Linux administrators that work with web hosting know how is it important to keep correct character encoding of the html documents.
From the following article you’ll learn how to check a file’s encoding from the command-line in Linux.
You will also find the best solution to convert text files between different charsets.
I’ll also show the most common examples of how to convert a file’s encoding between CP1251 (Windows-1251, Cyrillic), UTF-8 , ISO-8859-1 and ASCII charsets.
Cool Tip: Want see your native language in the Linux terminal? Simply change locale! Read more →
Check a File’s Encoding
Use the following command to check what encoding is used in a file:
Option | Description |
---|---|
-b , —brief | Don’t print filename (brief mode) |
-i , —mime | Print filetype and encoding |
Check the encoding of the file in.txt :
Change a File’s Encoding
Use the following command to change the encoding of a file:
Option | Description |
---|---|
-f , —from-code | Convert a file’s encoding from charset |
-t , —to-code | Convert a file’s encoding to charset |
-o , —output | Specify output file (instead of stdout) |
Change a file’s encoding from CP1251 (Windows-1251, Cyrillic) charset to UTF-8 :
Change a file’s encoding from ISO-8859-1 charset to and save it to out.txt :
Change a file’s encoding from ASCII to UTF-8 :
Change a file’s encoding from UTF-8 charset to ASCII :
Illegal input sequence at position: As UTF-8 can contain characters that can’t be encoded with ASCII, the iconv will generate the error message “illegal input sequence at position” unless you tell it to strip all non-ASCII characters using the -c option.
Option | Description |
---|---|
-c | Omit invalid characters from the output |
You can lose characters: Note that if you use the iconv with the -c option, nonconvertible characters will be lost.
This concerns in particular Windows machines with Cyrillic.
You have copied some file from Windows to Linux, but when you open it in Linux, you see “Êàêèå-òî êðàêîçÿáðû” – WTF!?
Don’t panic – such strings can be easily converted from CP1251 (Windows-1251, Cyrillic) charset to UTF-8 with:
List All Charsets
List all the known charsets in your Linux system:
Option | Description |
---|---|
-l , —list | List known charsets |
8 Replies to “HowTo: Check and Change File Encoding In Linux”
Thank you very much. Your reciept helped a lot!
I am running Linux Mint 18.1 with Cinnamon 3.2. I had some Czech characters in file names (e.g: Pešek.m4a). The š appeared as a ? and the filename included a warning about invalid encoding. I used convmv to convert the filenames (from iso-8859-1) to utf-8, but the š now appears as a different character (a square with 009A in it. I tried the file command you recommended, and got the answer that the charset was binary. How do I solve this? I would like to have the filenames include the correct utf-8 characters.
Thanks for your help–
Вообще-то есть 2 утилиты для определения кодировки. Первая этo file. Она хорошо определяет тип файла и юникодовские кодировки… А вот с ASCII кодировками глючит. Например все они выдаются как буд-то они iso-8859-1. Но это не так. Тут надо воспользоваться другой утилитой enca. Она в отличие от file очень хорошо работает с ASCII кодировками. Я не знаю такой утилиты, чтобы она одновременно хорошо работала и с ASCII и с юникодом… Но можно совместить их, написав свою. Это да. Кстати еnca может и перекодировать. Но я вам этого не советую. Потому что лучше всего это iconv. Он отлично работает со всеми типами кодировок и даже намного больше, с различными вариациями, включая BCD кодировки типа EBCDIC(это кодировки 70-80 годов, ещё до ДОСа…) Хотя тех систем давно нет, а файлов полно… Я не знаю ничего лучше для перекодировки чем iconv. Я думаю всё таки что file не определяет ASCII кодировки потому что не зарегистрированы соответствующие mime-types для этих кодировок… Это плохо. Потому что лучшие кодировки это ASCII.
Для этого есть много причин. И я не знаю ни одной разумной почему надо пользоваться юникодовскими кроме фразы “США так решило…” И навязывают всем их, особенно эту utf-8. Это худшее для кодирования текста что когда либо было! А главная причина чтобы не пользоваться utf-8, а пользоваться ASCII это то, что пользоваться чем-то иным никогда не имеет смысла. Даже в вебе. Хотите значки? Используйте символьные шрифты, их полно. Не вижу проблем… Почему я должен делать для корейцев, арабов или китайцев? Не хочу. Мне всегда хватало русского, в крайнем случае английского. Зачем мне ихние поганые языки и кодировки? Теперь про ASCII. KOI8-R это вычурная кодировка. Там русские буквы идут не по порядку. Нормальных только 2: это CP1251 и DOS866. В зависимости от того для чего. Если для графики, то безусловно CP1251. А если для полноценной псевдографики, то лучше DOS866 не придумали. Они не идеальны, но почти… Плохость utf-8 для русских текстов ещё и в том, что там каждая буква занимает 2 байта. Там ещё такая фишка как во всех юникодах это indian… Это то, в каком порядке идут байты, вначале младший а потом старший(как в памяти по адресам, или буквы в словах при написании) или наоборот, как разряды в числе, вначале старшие а потом младшие. А если символ 3-х, 4-х и боле байтов(до 16-ти в utf-8) то там кол-во заморочек растёт в геометрической прогрессии! Он ещё и тормозит, ибо каждый раз надо вычислять длину символа по довольно сложному алгоритму! А ведь нам ничего этого не надо! Причём заметьте, ихние англицкие буквы идут по порядку, ничего не пропущено и все помещаются в 1-м байте… Т.е. это искусственно придуманые штуки не для избранных америкосов. Их это вообще не волнует. Они разом обошли все проблемы записав свой алфавит в начало таблицы! Но кто им дал такое право? А все остальные загнали куда подальше… Особенно китайцев! Но если использовать CP1251, то она работает очень быстро, без тормозов и заморочек! Так же как и английские буквы…
а вот дальше бардак. Правда сейчас нам приходится пользоваться этим utf-8, Нет систем в которых бы системная кодировка была бы ASCII. Уже перестали делать. И все файлы системные именно в uft-8. А если ты хочешь ASCII, то тебе придётся всё время перекодировать. Раньше так не надо было делать. Надеюсь наши всё же сделают свою систему без ихних штатовких костылей…
Уважаемый Анатолий, огромнейшее Вам спасибо за упоминание enca. очень помогла она мне сегодня. Хотя пост Ваш рассистский и странный, но, видимо, сильно наболело.
Источник