Несколько вопросов о кодировке символов файловой системы в Linux

12

Из-за большого объема обмена файлами между Windows ( кодировка GBK ) и Linux ( кодировка UTF-8 ), он легко столкнется с проблемами кодировки символов, такими как:

  • Файлы zip / tar, имя которых содержит китайские символы в системе Windows, разархивируйте / разархивируйте их в системе Linux.
  • запустить перенесенное устаревшее веб-приложение на Java (разработанное в системе Windows с использованием GBK-кодировки в JSP), которое записывает файлы с именами GBK-кодировки на диск.
  • ftp получает / помещает файлы с именами в кодировке GBK между FTP-сервером Windows и клиентом Linux.
  • переключить среду LANG в Linux.

Распространенной проблемой, о которой говорилось выше, является поиск / присвоение имен файлам. После googled я получил статью « Использование Unicode в Linux» http://www.linux.com/archive/feed/39912 , в которой говорится:

операционная система и многие утилиты не понимают, какие символы представляют байты в именах файлов.

Таким образом, возможно иметь 2 файла 中文 .txt с различной кодировкой:

[root@fedora test]# ls
????  中文
[root@fedora test]# ls | iconv -f GBK
中文
涓iconv: illegal input sequence at position 7
[root@fedora test]# ls 中文 && ls $'\xd6\xd0\xce\xc4'|iconv -f gbk
中文
中文

Вопросов:

  1. Можно ли настроить файловую систему linux, используя фиксированную кодировку символов (например, NTFS использует UTF-16 внутри) для хранения имен файлов независимо от среды LANG / LC_ALL?
  2. Или, что я на самом деле хочу спросить: возможно ли, чтобы имя файла 中文 .txt ( $'\xe4\xb8\xad\xe6\x96\x87.txt') в среде zh_CN.UTF-8 и имя файла 中文 .txt ( $'\xd6\xd0\xce\xc4.txt') в среде zh_CN.GBK ссылались на один и тот же файл ?
  3. Если это не настраивается, то можно ли исправить ядро ​​для преобразования кодировки символов между файловой системой и текущей средой (просто вопрос, а не запрос реализации)? и сколько производительности повлияет, если это возможно?
LiuYan 刘 研
источник
Вы можете решить эту проблему со стороны Windows, используя Cygwin 1.7, который автоматически выполняет преобразование между кодировкой UTF-16 файловой системы и любой кодировкой, указанной в настройках локали. По умолчанию используется UTF-8, поэтому, например, Cygwin tar будет кодировать имена файлов как UTF-8.
ak2
@ ak2 Спасибо, Cygwin действительно хорош, я использую его годами. Случай tar / zip является лишь примером, в реальной среде файлы zip / tar могут быть созданы другими (например, загрузить файл из Интернета).
LiuYan 研 研

Ответы:

8

Я немного переформулировал ваши вопросы по причинам, которые должны проявиться, когда вы прочитаете их последовательно.

1. Можно ли настроить файловую систему linux на использование фиксированной кодировки символов для хранения имен файлов независимо от среды LANG / LC_ALL?

Нет, это невозможно: как вы упоминаете в своем вопросе, имя файла UNIX - это просто последовательность байтов; ядро ничего не знает о кодировке, которая полностью является концепцией пользовательского пространства (т. е. уровня приложения).

Другими словами, ядро ​​ничего не знает о LANG/ LC_*, поэтому оно не может перевести.

2. Можно ли разрешить, чтобы разные имена файлов ссылались на один и тот же файл?

Вы можете иметь несколько записей каталога, ссылающихся на один и тот же файл; Вы можете сделать это с помощью жестких ссылок или символических ссылок .

Имейте в виду, однако, что имена файлов, которые недопустимы в текущей кодировке (например, ваша строка символов GBK, когда вы работаете в локали UTF-8), будут отображаться плохо, если вообще будут отображаться.

3. Можно ли пропатчить ядро ​​для перевода кодировки символов между файловой системой и текущей средой?

Вы не можете пропатчить ядро, чтобы сделать это (см. 1.), но вы можете - в теории - пропатчить библиотеку C (например, glibc), чтобы выполнить этот перевод, и всегда конвертировать имена файлов в UTF-8, когда он вызывает ядро, и преобразовать их обратно в текущую кодировку, когда он читает имя файла из ядра.

Более простой подход мог бы заключаться в написании оверлейной файловой системы с FUSE , которая просто перенаправляет любой запрос файловой системы в другое место после преобразования имени файла в / из UTF-8. В идеале вы могли бы смонтировать эту файловую систему ~/trans, и когда доступ к ней будет осуществлен, ~/trans/a/GBK/encoded/pathтогда к файловой системе FUSE будет действительно доступ /a/UTF-8/encoded/path.

Однако проблема этих подходов заключается в следующем: что вы делаете с файлами, которые уже существуют в вашей файловой системе и не имеют кодировки UTF-8? Вы не можете просто передать их непереведенным, потому что тогда вы не знаете, как их преобразовать; Вы не можете искажать их, переводя недопустимые последовательности символов, ?потому что это может создать конфликты ...

Риккардо Мурри
источник
4
Такая оверлейная файловая система существует: Convmvfs .
Жиль "ТАК - перестань быть злым"
1

Что вы можете сделать, так это ограничить количество поддерживаемых локалей только локалями UTF-8.

http://www.fifi.org/cgi-bin/man2html/usr/share/man/man5/locale.gen.5

Позволь мне быть
источник
2
Лично я хотел бы, чтобы в мире существовала только одна кодировка кодировки (UTF-8), но все еще существует устаревшее приложение, и необходимо обеспечить взаимодействие между Windows и Linux, большинство людей должно столкнуться с этим кошмаром.
LiuYan 研 研