Varias preguntas sobre la codificación de caracteres del sistema de archivos en Linux

12

Debido a una gran cantidad de trabajos de intercambio de archivos entre Windows ( codificación GBK ) y Linux ( codificación UTF-8 ), encontrará problemas de codificación de caracteres fácilmente, tales como:

  • archivos zip / tar cuyo nombre contiene caracteres chinos en el sistema Windows, descomprímalo / descomprímalo en el sistema Linux.
  • ejecute la aplicación web Java migrada heredada (diseñada en el sistema Windows, usando codificación GBK en JSP) que escribe en el disco archivos con codificación GBK.
  • ftp get / put GBK-encoding-named files entre el servidor FTP de Windows y el cliente Linux.
  • cambiar el entorno LANG en Linux.

El problema común de lo mencionado anteriormente es la localización / nomenclatura de archivos. Después de buscar en Google, recibí un artículo sobre el uso de Unicode en Linux http://www.linux.com/archive/feed/39912 , que decía:

el sistema operativo y muchas utilidades no se dan cuenta de qué caracteres representan los bytes en los nombres de archivo.

Por lo tanto, es posible tener 2 archivos .txt con codificación diferente:

[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
中文
中文

Preguntas:

  1. ¿Es posible configurar el sistema de archivos de Linux usando codificación de caracteres fijos (como NTFS usa UTF-16 internamente) para almacenar nombres de archivos independientemente del entorno LANG / LC_ALL?
  2. O, lo que realmente quiero preguntar es: ¿Es posible dejar que el nombre de archivo 中文 .txt ( $'\xe4\xb8\xad\xe6\x96\x87.txt') en el entorno zh_CN.UTF-8 y el nombre de archivo 中文 .txt ( $'\xd6\xd0\xce\xc4.txt') en el entorno zh_CN.GBK se refieran al mismo archivo ?
  3. Si no es configurable, ¿es posible parchear el núcleo para traducir la codificación de caracteres entre el sistema de archivos y el entorno actual (solo una pregunta, no solicitar la implementación)? y cuánto efecto tiene si es posible?
LiuYan 刘 研
fuente
Puede abordar el problema desde el lado de Windows utilizando Cygwin 1.7, que se traduce automáticamente entre la codificación UTF-16 del sistema de archivos y cualquier codificación que se haya especificado en la configuración regional. Su valor predeterminado es UTF-8, por lo que, por ejemplo, el tar de Cygwin codificaría los nombres de archivo como UTF-8.
ak2
@ ak2 Gracias, Cygwin es realmente bueno, lo he usado por años. El caso tar / zip es solo un ejemplo, en un entorno real, los archivos zip / tar pueden ser creados por otros (como descargar un archivo de internet).
LiuYan 刘 研

Respuestas:

8

He reformulado un poco sus preguntas, por razones que deberían parecer evidentes cuando las lee en secuencia.

1. ¿Es posible configurar el sistema de archivos de Linux usando codificación de caracteres fijos para almacenar nombres de archivos independientemente del entorno LANG / LC_ALL?

No, esto no es posible: como mencionas en tu pregunta, un nombre de archivo UNIX es solo una secuencia de bytes; el kernel no sabe nada acerca de la codificación, que es completamente un concepto de espacio de usuario (es decir, de nivel de aplicación).

En otras palabras, el núcleo no sabe nada sobre LANG/ LC_*, por lo que no puede traducir.

2. ¿Es posible dejar que diferentes nombres de archivo se refieran al mismo archivo?

Puede tener múltiples entradas de directorio que hagan referencia al mismo archivo; puedes hacerlo a través de enlaces duros o enlaces simbólicos .

Sin embargo, tenga en cuenta que los nombres de archivo que no son válidos en la codificación actual (por ejemplo, su cadena de caracteres GBK cuando trabaja en un entorno local UTF-8) se mostrarán mal, si es que lo hacen.

3. ¿Es posible parchear el núcleo para traducir la codificación de caracteres entre el sistema de archivos y el entorno actual?

No puede parchear el kernel para hacer esto (ver 1.), pero podría, en teoría, parchear la biblioteca C (por ejemplo, glibc) para realizar esta traducción, y siempre convertir los nombres de archivo a UTF-8 cuando llama al kernel, y convertirlos nuevamente a la codificación actual cuando lee un nombre de archivo del núcleo.

Un enfoque más simple podría ser escribir un sistema de archivos superpuesto con FUSE , que simplemente redirige cualquier solicitud del sistema de archivos a otra ubicación después de convertir el nombre del archivo a / desde UTF-8. Idealmente, podría montar este sistema de archivos ~/trans, y cuando se realiza un acceso al ~/trans/a/GBK/encoded/pathsistema de archivos FUSE realmente accede /a/UTF-8/encoded/path.

Sin embargo, el problema con estos enfoques es: ¿qué hace con los archivos que ya existen en su sistema de archivos y que no están codificados con UTF-8? No puedes simplemente pasarlos sin traducir, porque entonces no sabes cómo convertirlos; no puedes destrozarlos traduciendo secuencias de caracteres no válidas ?porque eso podría crear conflictos ...

Riccardo Murri
fuente
44
Tal sistema de archivos superpuesto existe: Convmvfs .
Gilles 'SO- deja de ser malvado'
1

Lo que puede hacer es limitar la cantidad de configuraciones regionales admitidas a solo configuraciones regionales UTF-8.

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

Déjame ser
fuente
2
Personalmente, desearía que solo haya 1 codificación de juego de caracteres (UTF-8) en el mundo, pero todavía hay una aplicación heredada en ejecución, y se debe lograr la interoperabilidad entre Windows y Linux, la mayoría de las personas deben enfrentar esta pesadilla.
LiuYan 刘 研