Várias perguntas sobre a codificação de caracteres do sistema de arquivos no linux


12

Devido a muitas trocas de arquivos entre o Windows ( codificação GBK ) e o Linux ( codificação UTF-8 ), ele encontrará facilmente problemas de codificação de caracteres, como:

  • arquivos zip / tar cujo nome contenha caracteres chineses no sistema Windows, descompacte / descompacte-o no sistema Linux.
  • execute o aplicativo da web java herdado migrado (projetado no sistema Windows, usando a codificação GBK no JSP) que grava arquivos nomeados pela codificação GBK no disco.
  • O ftp obtém / coloca arquivos com o nome de codificação GBK entre o servidor FTP do Windows e o cliente Linux.
  • alternar o ambiente LANG no Linux.

O problema comum do mencionado anteriormente é a localização / nomeação de arquivos. Após pesquisar no Google, recebi um artigo Usando o Unicode no Linux http://www.linux.com/archive/feed/39912 , que dizia:

o sistema operacional e muitos utilitários não percebem quais caracteres os bytes nos nomes de arquivo representam.

Portanto, é possível ter 2 arquivos .txt com codificação 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
中文
中文

Questões:

  1. É possível configurar o sistema de arquivos linux usando codificação de caracteres fixa (como o NTFS usa UTF-16 internamente) para armazenar nomes de arquivos, independentemente do ambiente LANG / LC_ALL?
  2. Ou o que realmente quero perguntar é: É possível permitir que o nome do arquivo 中文 .txt ( $'\xe4\xb8\xad\xe6\x96\x87.txt') no ambiente zh_CN.UTF-8 e o nome do arquivo 中文 .txt ( $'\xd6\xd0\xce\xc4.txt') no ambiente zh_CN.GBK se refiram ao mesmo arquivo ?
  3. Se não for configurável, é possível corrigir o kernel para converter a codificação de caracteres entre o sistema de arquivos e o ambiente atual (apenas uma pergunta, não solicitar implementação)? e quanto desempenho afeta, se possível?

Você pode resolver o problema do lado do Windows usando o Cygwin 1.7, que é traduzido automaticamente entre a codificação UTF-16 do sistema de arquivos e a codificação especificada nas configurações de localidade. O padrão é UTF-8, portanto, por exemplo, o tar Cygwin codificaria os nomes de arquivos como UTF-8.
AK2

@ ak2 Obrigado, Cygwin é realmente bom, eu tenho usado por anos. O caso tar / zip é apenas um exemplo. No ambiente real, os arquivos zip / tar podem ser criados por outras pessoas (como baixar um arquivo da Internet).
LiuYan

Respostas:


8

Eu reformulei suas perguntas um pouco, por razões que devem aparecer evidentes quando você as lê em sequência.

1. É possível configurar o sistema de arquivos linux usando codificação de caracteres fixa para armazenar nomes de arquivos, independentemente do ambiente LANG / LC_ALL?

Não, isso não é possível: como você mencionou na sua pergunta, um nome de arquivo UNIX é apenas uma sequência de bytes; o kernel não sabe nada sobre a codificação, que é inteiramente um conceito de espaço do usuário (ou seja, no nível do aplicativo).

Em outras palavras, o kernel não sabe nada sobre LANG/LC_* , portanto não pode traduzir.

2. É possível permitir que nomes de arquivos diferentes se refiram ao mesmo arquivo?

Você pode ter várias entradas de diretório referentes ao mesmo arquivo; você pode fazer isso por meio de links físicos ou simbólicos .

Esteja ciente, no entanto, de que os nomes de arquivo que não são válidos na codificação atual (por exemplo, sua cadeia de caracteres GBK quando você está trabalhando em um código de idioma UTF-8) serão exibidos incorretamente, se houver.

3. É possível corrigir o kernel para converter a codificação de caracteres entre o sistema de arquivos e o ambiente atual?

Você não pode corrigir o kernel para fazer isso (consulte 1.), mas poderia, em teoria, corrigir a biblioteca C (por exemplo, glibc) para executar esta tradução e sempre converter nomes de arquivos em UTF-8 quando ele chama o kernel, e converta-os novamente para a codificação atual quando ler um nome de arquivo do kernel.

Uma abordagem mais simples poderia ser escrever um sistema de arquivos de sobreposição com o FUSE , que apenas redireciona qualquer solicitação do sistema de arquivos para outro local depois de converter o nome do arquivo para / de UTF-8. Idealmente, você pode montar esse sistema de arquivos ~/transe, quando um acesso é feito ~/trans/a/GBK/encoded/path, o sistema de arquivos FUSE realmente acessa /a/UTF-8/encoded/path .

No entanto, o problema com essas abordagens é: o que você faz com os arquivos que já existem no seu sistema de arquivos e não são codificados em UTF-8? Você não pode simplesmente passá-los sem tradução, porque então você não sabe como convertê-los; você não pode modificá-los traduzindo seqüências de caracteres inválidas, ?pois isso pode criar conflitos ...


4
Existe um sistema de arquivos de sobreposição: Convmvfs .
Gilles 'SO- stop be evil'

1

O que você pode fazer é limitar a quantidade de códigos de idioma suportados a apenas códigos de idioma UTF-8.

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


2
Pessoalmente, eu gostaria que houvesse apenas 1 codificação de charset (UTF-8) no mundo, mas ainda há aplicativos herdados em execução e a interoperabilidade entre Windows e Linux deve ser alcançada, a maioria das pessoas deve enfrentar esse pesadelo.
LiuYan
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.