Plusieurs questions sur l'encodage de caractères du système de fichiers sous Linux

12

En raison de nombreux échanges de fichiers entre Windows ( encodage GBK ) et Linux ( encodage UTF-8 ), il rencontrera facilement des problèmes d'encodage de caractères, tels que:

  • fichiers zip / tar dont le nom contient des caractères chinois sur le système Windows, décompressez / décompressez-le dans le système Linux.
  • exécuter l'application Web Java héritée migrée (conçue sur le système Windows, en utilisant le codage GBK dans JSP) qui écrit les fichiers nommés par codage GBK sur le disque.
  • ftp récupère / place les fichiers nommés par encodage GBK entre le serveur FTP Windows et le client Linux.
  • changer l'environnement LANG sous Linux.

Le problème commun des précédents mentionnés est la localisation / la dénomination des fichiers. Après avoir recherché sur Google, j'ai reçu un article sur l' utilisation d'Unicode sous Linux http://www.linux.com/archive/feed/39912 , qui disait:

le système d'exploitation et de nombreux utilitaires ne réalisent pas quels caractères les octets des noms de fichiers représentent.

Ainsi, il est possible d'avoir 2 fichiers 中文 .txt avec un encodage différent:

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

Des questions:

  1. Est-il possible de configurer le système de fichiers linux en utilisant un codage de caractères fixe (comme NTFS utilise UTF-16 en interne) pour stocker les noms de fichiers indépendamment de l'environnement LANG / LC_ALL?
  2. Ou, ce que je veux vraiment demander, c'est: est-il possible de laisser le nom de fichier 中文 .txt ( $'\xe4\xb8\xad\xe6\x96\x87.txt') dans l'environnement zh_CN.UTF-8 et le nom de fichier 中文 .txt ( $'\xd6\xd0\xce\xc4.txt') dans l'environnement zh_CN.GBK faire référence au même fichier ?
  3. Si ce n'est pas configurable, est-il possible de patcher le noyau pour traduire le codage des caractères entre le système de fichiers et l'environnement actuel (juste une question, pas de demande d'implémentation)? et combien de con performance si c'est possible?
LiuYan 刘 研
la source
Vous pouvez résoudre le problème du côté de Windows en utilisant Cygwin 1.7, qui se traduit automatiquement entre le codage UTF-16 du système de fichiers et le codage spécifié dans les paramètres régionaux. Il est par défaut UTF-8, donc par exemple Cygwin tar encoderait les noms de fichiers en UTF-8.
ak2
@ ak2 Merci, Cygwin est vraiment bon, je l'utilise depuis des années. Le boîtier tar / zip n'est qu'un exemple, dans un environnement réel, les fichiers zip / tar peuvent être créés par d'autres (comme le téléchargement d'un fichier sur Internet).
LiuYan 刘 研

Réponses:

8

J'ai reformulé un peu vos questions, pour des raisons qui devraient apparaître évidentes lorsque vous les lisez dans l'ordre.

1. Est-il possible de configurer le système de fichiers linux en utilisant un codage de caractères fixe pour stocker les noms de fichiers indépendamment de l'environnement LANG / LC_ALL?

Non, ce n'est pas possible: comme vous le mentionnez dans votre question, un nom de fichier UNIX n'est qu'une séquence d'octets; le noyau ne sait rien de l'encodage, qui est entièrement un concept d'espace utilisateur (c'est-à-dire au niveau de l'application).

En d'autres termes, le noyau ne sait rien de LANG/ LC_*, il ne peut donc pas traduire.

2. Est-il possible de laisser des noms de fichiers différents faire référence au même fichier?

Vous pouvez avoir plusieurs entrées de répertoire faisant référence au même fichier; vous pouvez le faire grâce à des liens physiques ou des liens symboliques .

Sachez toutefois que les noms de fichiers qui ne sont pas valides dans l'encodage actuel (par exemple, votre chaîne de caractères GBK lorsque vous travaillez dans un environnement local UTF-8) s'afficheront mal, voire pas du tout.

3. Est-il possible de patcher le noyau pour traduire le codage de caractères entre le système de fichiers et l'environnement actuel?

Vous ne pouvez pas patcher le noyau pour ce faire (voir 1.), mais vous pourriez -en théorie- patcher la bibliothèque C (par exemple, glibc) pour effectuer cette traduction, et toujours convertir les noms de fichiers en UTF-8 quand il appelle le noyau, et les reconvertir à l'encodage actuel quand il lit un nom de fichier à partir du noyau.

Une approche plus simple pourrait être d'écrire un système de fichiers en superposition avec FUSE , qui redirige simplement toute demande de système de fichiers vers un autre emplacement après la conversion du nom de fichier vers / depuis UTF-8. Idéalement, vous pouvez monter ce système de fichiers dans ~/trans, et lorsqu'un accès est fait, ~/trans/a/GBK/encoded/pathle système de fichiers FUSE y accède vraiment /a/UTF-8/encoded/path.

Cependant, le problème avec ces approches est: que faites-vous avec les fichiers qui existent déjà sur votre système de fichiers et qui ne sont pas encodés en UTF-8? Vous ne pouvez pas simplement les transmettre non traduits, car alors vous ne savez pas comment les convertir; vous ne pouvez pas les modifier en traduisant des séquences de caractères non valides ?car cela pourrait créer des conflits ...

Riccardo Murri
la source
4
Un tel système de fichiers de superposition existe: Convmvfs .
Gilles 'SO- arrête d'être méchant'
1

Ce que vous pouvez faire est de limiter la quantité de paramètres régionaux pris en charge aux seuls paramètres régionaux UTF-8.

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

Laisse-moi tranquille
la source
2
Personnellement, je souhaite qu'il n'y ait qu'un seul codage de jeu de caractères (UTF-8) dans le monde, mais il y a toujours une application héritée, et l'interopérabilité entre Windows et Linux doit être réalisée, la plupart des gens doivent faire face à ce cauchemar.
LiuYan 刘 研