Dmi*_*rov 12 character-encoding zip
这里有一些关于以流形式存储在 zip 文件(希伯来语、中文、日语或韩语)中的文件名称中的非 ASCII 字母的问题。然而,提供的解决方案都没有帮助我使用来自 Windows 机器的带有西里尔字母的 zipfile。
该文件本身有一个西里尔文名称(??????.zip - 可下载链接)。这是一个包含零长度内容的档案,仅用于说明目的。
unzip -l 印刷:
Archive: ??????.zip
Length Date Time Name
--------- ---------- ----- ----
0 2017-05-03 18:19 ???????/ict_inf.pdf
--------- -------
0 1 file
Run Code Online (Sandbox Code Playgroud)
丑陋???????代表字节序列C9 AB DF E8 AB DF BC AB DF。
我知道(通过使用 GMail 预览功能)这应该是
Archive: ??????.zip
Length Date Time Name
--------- ---------- ----- ----
0 2017-05-03 18:19 ?????????/ict_inf.pdf
--------- -------
0 1 file
Run Code Online (Sandbox Code Playgroud)
那就是我们需要映射C9 AB DF E8 AB DF BC AB DF到?????????.
有几种常用的 8 位西里尔文编码:CP1251、CP866、ISO8859-5,但是他们会将这个字编码为不同的字节序列:
? ? ? ? ? ? ? ? ?
CP866: 90 AE E1 8A AE E1 AC AE E1
CP1251: D0 EE F1 CA EE F1 EC EE F1
ISO8859-5: C0 DE E1 BA DE E1 DC DE E1
Run Code Online (Sandbox Code Playgroud)
显然,常用的 8 位西里尔文编码都不会像这样将输入名称解码为输出名称。这里有一些更复杂的事情在起作用。
如果我们知道如何解码名称,那么使用适当的find脚本(https://unix.stackexchange.com/a/252000/17649)在提取后重命名文件将很容易,例如
find -mindepth 1 -exec sh -c 'mv "$1" "$(echo "$1" | here-goes-the-decoding pipeline )"' sh {} \;
Run Code Online (Sandbox Code Playgroud)
或convvv实用程序。
我在 OpenNET.ru 论坛上找到了一个解决方案,这是一个流行的俄语资源,自 1996 年以来一直致力于开源软件和技术。OpenNET 上的一篇文章表明 Info-ZIP,曾经是处理 ZIP 的流行工具集运行 MS-DOS 的计算机上的存档假定在 MS-DOS 上只有一种 8 位编码,即 CP850,因此所有文件名都通过CP850->CP1252转换自动运行。CP1252 可能被选为最流行的 ISO-8859-1 字符集编码近似值。
因此,在提取包含西里尔文文件名的存档后运行的正确 find 命令将是
find -mindepth 1 -exec sh -c 'mv "$1" "$(echo "$1" | iconv -f cp1252 -t cp850 | iconv -f cp866 )"' sh {} \;
Run Code Online (Sandbox Code Playgroud)
有趣的是,可以找到不使用 CP1252 而是使用 ISO-8859-1 的建议。情况似乎并非如此,因为我遇到的一些档案iconv -f iso8859-1 -t cp850在iconv -f cp1252 -t cp850成功转换时失败。
回到个人角色
? ? ? ? ? ? ? ? ?
CP866: 90 AE E1 8A AE E1 AC AE E1
Run Code Online (Sandbox Code Playgroud)
现在应用 CP850 -> CP1252 结果是C9 AB DF E8 AB DF BC AB DF. 正是我们观察到的序列。
另一个有用的命令是
unzip -l ?????????.zip | grep -aEv '^Archive:' | iconv -f iso8859-1 -t cp850 | iconv -f cp866
Run Code Online (Sandbox Code Playgroud)
从存档中获取文件列表
Length Date Time Name
--------- ---------- ----- ----
0 2017-05-03 18:19 ?????????/ict_inf.pdf
--------- -------
0 1 file
Run Code Online (Sandbox Code Playgroud)
过滤掉以开头的行Archive:是一种保护,以隐藏存档名称以防止转换。
与“最近”infozip 一起使用的 ZIP 文件显示正确的文件名:
\n\nunzip -l Russian-\xd0\x9a\xd0\xbe\xd1\x81\xd0\xbc\xd0\xbe\xd1\x81.zip \nArchive: Russian-\xd0\x9a\xd0\xbe\xd1\x81\xd0\xbc\xd0\xbe\xd1\x81.zip\n Length Date Time Name\n--------- ---------- ----- ----\n 0 2017-05-03 18:19 \xd0\xa0\xd0\xbe\xd1\x81\xd0\x9a\xd0\xbe\xd1\x81\xd0\xbc\xd0\xbe\xd1\x81/ict_inf.pdf\n--------- -------\n 0 1 file\n\nRun Code Online (Sandbox Code Playgroud)\n\n并且 unzip 在解压时正确创建\xd0\xa0\xd0\xbe\xd1\x81\xd0\x9a\xd0\xbe\xd1\x81\xd0\xbc\xd0\xbe\xd1\x81/目录。
infozip 很久以前就添加了 UTF-8 支持。我的 Ubuntu 上的可执行文件:
\n\nUnZip 6.00, 20 April 2009\nZip 3.0, July 5th 2008\nRun Code Online (Sandbox Code Playgroud)\n\n所以你的问题可能是一个古老的InfoZip版本(或者是没有UTF-8支持编译的版本)
\n\n在我的版本中,strings /usr/bin/unzip | grep -A8 -B8 \'UTF-8\'除其他外,产生:
ZIP64_SUPPORT (archives using Zip64 for large files supported)\nLARGE_FILE_SUPPORT (large files over 2 GiB supported)\nother\nUTF-8\nUNICODE_SUPPORT [wide-chars, char coding: %s] (handle UTF-8 paths)\nUSE_DEFLATE64 (PKZIP 4.x Deflate64(tm) supported)\nUSE_UNSHRINK (PKZIP/Zip 1.x unshrinking method supported)\nRun Code Online (Sandbox Code Playgroud)\n\n这似乎与编译/构建选项有关
\n| 归档时间: |
|
| 查看次数: |
4371 次 |
| 最近记录: |