为什么我的文件名在Linux中看起来是“普通”的,而在Windows中却不是远程的?


11

与同事一起工作时,我发现了一个奇怪的问题,似乎与编码有关。我们正在与具有足够简单的文件名,如一些图像时city.gifwine.gif,但正如人们所预料的事情开始使用特殊字符,例如当更多复杂的éëà。我们还正在处理具有这些字符的荷兰数据,例如cafépub)。(我们无法控制文件的来源。)这是开始出现问题的地方。以下文件名仅是示例。带有变音符号的其他字符也会出现此问题。

café-2.png
cafetaria.png
café.png

第一项和最后一项应在其中带有重音符号e(重音aigu,é)。这样便可以在Linux(CentOS 6和7)的终端上运行它ls。但是Windows来了!(使用Windows 10,64位。)在Windows上通过SSL与我们的服务器通过SSL连接,然后调用时ls,上面的列表如下所示:

café-2.png
cafetaria.png
caf▒.png

如您所愿,第一行仍带有重音符号e é,而第三行则没有。相反,我看到了这个字符-它是medium shadeunicode(十进制数为1818)。这本身很奇怪。但是,当我通过SFTP和Filezilla(仍在Windows上)连接时,会看到以下内容:

café-2.png
cafetaria.png
café.png

因此,现在情况有所好转:在第一个中,é已更改为顺序,在第三个中,一切都很好。我在这里发现,这很可能是由于Latin-1 <-> UTF-8转换出错(如果我正确的话)。但这不可能是所有发生的事情,对吧?

Linux显示了我们所期望的一切,Windows显示了似乎不一致的行为,具体取决于我们查看文件名的方式(SSH(putty)或SFTP(filezilla))。有没有一种方法可以“标准化”这些文件名(即编辑它们),并确保每个操作系统上的文件名都相同;或至少是一致的,如果是的话,如何?UTF-8是我们选择的编码。

即使这可能只是一个美学问题,但事实并非如此。尝试从Linux服务器通过Windows中的SFTP下载内容时,我无法下载出现上述问题的文件。Filezilla将抛出诸如的错误Can't download file café-2.png: café-2.png does not exist on the server。在我看来,Filezilla会读取目录和文件名,以某种编码对其进行解释,然后将GET请求及其解释发送给服务器,但是该解释与Linux文件名不同,因此找不到该文件。

最终,如果有解决方案,那将是很好的,尽管我也对为什么会发生这种情况感兴趣。是否因为映像文件可能是在不同的操作系统上创建而发生的?是因为Linux服务器将其解释为错误而发生,还是Windows混乱了?希望有一种解决方案,我们可以联系我们的系统管理员,要求他们打开服务器配置中的开关,但恐怕并非如此简单。


1
这与客户端(PuTTY等)及其配置有关,与Windows不相关。对于PuTTY,这是在翻译部分完成的。
Thomas Dickey

2
看起来有点像“café-2.png”中的é是UTF-8编码的,但是“café.png”中的é是ISO-8859-1编码的。你能运行python -c "import sys; print(repr(sys.argv[1]))" café-2.pngpython -c "import sys; print(repr(sys.argv[1]))" café.png
Oskar Skog's

@OskarSkog我会在早上尝试。但是我一直以为文件名没有“编码”,换句话说:就是操作系统想要的。那是否意味着不同的文件是在不同的操作系统上创建的?(我们无法控制文件的来源。)
Bram Vanroy

在像Unix这样的操作系统上,文件名只是一个字节字符串。字符的概念更高。
Oskar Skog's

1
甚至没有答案或解决方案,只是在追求道路上的一种思考。从OP看来,文件可能具有各种来源,无法控制由源生成的名称,现在应用过滤器更正传入的文件名假冒为时已晚。该解决方案可能涉及在服务器上运行可以检测并更正文件名错误的脚本,甚至可能标准化用于名称的字符集/代码页。然后,OP可以在Filezilla或其他客户端中使用相同的代码页,然后一切正常。超越了我的技能,但也许可以带头。
user207673 '17

Answers:


11

但是Windows来了!

Windows与此无关。您可以使用(例如)GNOME Terminal的本地实例来重现此相同的行为,并为其选择适当的终端编码并为其配置适当的语言环境ls,而根本不需要任何Windows 。

Windows唯一要做的就是清楚地显示正在发生的事情。您的Windows FTP程序正在获取文件名中的字节,并将其显示为代码页1252中的相关代码点。这是单字节编码,几乎所有高于0x1F的内容都带有可打印的字形,它告诉我们确切的文件名中的字节是。

您的第二个文件名基本上没有任何意义,但是第一个和第三个文件说明了问题。

  • 第一个文件名是字节序列63 61 66 c3 a9 2d 32 2e 70 6e 67—在代码页1252中为café-2.png。也是的UTF-8编码café-2.png
  • 第三个文件名是字节序列63 61 66 e9 2e 70 6e 67—在代码页1252中为café.png。但是,它不是有效的UTF-8编码。 e9开始一个不完整的字符编码序列。

因此,发生的事情是,这些操作使用代码页1252,而是使用UTF-8,即您的SSH会话和本地终端模拟器正在以相同的方式处理有效的 UTF-8,但正在处理对无效 UTF-8两种不同的方式:

  • 显示块图形的人很可能只是将该块图形用作无效UTF-8序列的通用替换输出字符
  • 显示字母的é代码在遇到无效编码时会退回到代码页1252。

您的根本问题是一个系统,该系统以某种方式生成一些编码为UTF-8的文件名和其他在代码页1252中编码的文件名。


我不同意Windows与之无关。在其他Linux上可能不会发生。问题是默认编码,并且afaik Windows已经(或至少已经使用)其CP而不是UTF,即使在同一国家/地区的同一OS上,也会出现此问题。您可以复制这个在Linux,但Linux的是在选择的Unicode更一致
MatthewRock

嗨,您好!感谢您的详尽回答。您将注意力集中在正在发生的事情上,这很不错:我一直喜欢了解正在发生的事情。但是您也许可以阐明为什么会发生这种情况,以及我们如何应对这种不一致带来的问题?我添加了两个段落以阐明我的意思。
Bram Vanroy

我想知道为什么两个“咖啡馆”在不同时显示为相同。GNU的ls(1)是否有荒谬的编码错误处理?
奥斯卡·斯科格

@MatthewRock在这种情况下,我认为Windows确实与它无关。我对M $的大部分功能都不满意,并乐于承认其许多弊端,但我看不到应有的责备。答案很明确,问题在于名称本身的字节值。在这种情况下,Windows暴露了症状,但这不是问题。当温度计显示发烧为104°时,问题就不多于温度计。问题出在任何具有在OP尝试访问的文件的服务器上创建名称的进程。
user207673

您能否提供更多信息和可能的解决方案?否则,我一无所获。
Bram Vanroy
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.