用给定的编码解压缩ZIP


26

我得到了ZIP文件,其中包含文件,文件名采用某种编码。假设我知道这些文件名的编码,但是我仍然不知道如何正确解压缩它们。

这是示例文件,其中包含一个文件“【SSK字幕组】吸血鬼日记吸血鬼日记S06E12.ass”

我知道使用的编码是GB18030(中文)

问题是-如何使用unzip或其他CLI实用工具在FreeBSD中解压缩该文件以获取正确的编码文件名?我尽了我所能,但结果却永远不好。请帮忙。

我在OSX上尝试过:

MBP1:test 2ge$ bsdtar xf gb18030.zip
MBP1:test 2ge$ ls
%A1%BESSK%D7%D6Ļ%D7顿The Vampire Diaries %CE%FCѪ%B9%ED%C8ռ%C7S06E12/      gb18030.zip
MBP1:test 2ge$ cd %A1%BESSK%D7%D6Ļ%D7顿The\ Vampire\ Diaries\ %CE%FCѪ%B9%ED%C8ռ%C7S06E12/
MBP1:%A1%BESSK%D7%D6Ļ%D7顿The Vampire Diaries %CE%FCѪ%B9%ED%C8ռ%C7S06E12 2ge$ ls
%A1%BESSK%D7%D6Ļ%D7顿The Vampire Diaries %CE%FCѪ%B9%ED%C8ռ%C7S06E12.ass*
MBP1:%A1%BESSK%D7%D6Ļ%D7顿The Vampire Diaries %CE%FCѪ%B9%ED%C8ռ%C7S06E12 2ge$ find . | iconv -f gb18030 -t utf-8
.
./%A1%BESSK%D7%D6L抬%D7椤縏he Vampire Diaries %CE%FC血%B9%ED%C8占%C7S06E12.ass 
MBP1:%A1%BESSK%D7%D6Ļ%D7顿The Vampire Diaries %CE%FCѪ%B9%ED%C8ռ%C7S06E12 2ge$ convmv -r -f gb18030 -t utf-8 --notest .
Skipping, already UTF-8: ./%A1%BESSK%D7%D6Ļ%D7顿The Vampire Diaries %CE%FCѪ%B9%ED%C8ռ%C7S06E12.ass
Ready!

我尝试用解压缩进行类似操作,但出现类似问题。

谢谢,现在尝试使用免费的BSD,我在OSX(终端)上使用SSH进行连接:

# locale
LANG=
LC_CTYPE="C"
LC_COLLATE="C"
LC_TIME="C"
LC_NUMERIC="C"
LC_MONETARY="C"
LC_MESSAGES="C"
LC_ALL=C

首先,我要正确显示中文名称。我变了

setenv LC_ALL zh_CN.GB18030
setenv LANG zh_CN.GB18030

然后,我下载了文件并尝试“ ls”查看正确的字符,但不走运。因此,我认为我必须先解决中文语言环境,才能验证何时获得正确的结果,实际上我可以进行比较。您还能帮我吗?

Answers:


22

这是我在Ubuntu 16.04上执行的操作,只要我知道该编码是什么,就可以将其解压缩为任何编码。由于FreeBSD仅依赖于广泛可用的unzip工具,因此该方法也应适用于FreeBSD 。

  1. 我仔细检查了编码的确切名称,以免拼写错误:https : //www.iana.org/assignments/character-sets/character-sets.xhtml

  2. 我只是跑

    $ unzip -O <encoding> <filename> -d <target_dir>
    

    要么

    $ unzip -I <encoding> <filename> -d <target_dir>
    

    在此处-O-I根据说明进行选择:

    $ unzip -h
    UnZip 6.00 of 20 April 2009, by Debian. Original by Info-ZIP.
      ...
      -O CHARSET  specify a character encoding for DOS, Windows and OS/2 archives
      -I CHARSET  specify a character encoding for UNIX and other archives
      ...
    

    这意味着我只是尝试-O并且应该可以工作,因为没有很多人会.zip在Unix中创建文件...


因此,对于您的特定示例:

  1. 确切的编码名称是GB18030

  2. 我使用-O标志和:

    $ unzip -O GB18030 gb18030.zip -d target_dir
    Archive:  gb18030.zip
       creating: target_dir/【SSK字幕组】The Vampire Diaries 吸血鬼日记S06E12/
      inflating: target_dir/【SSK字幕组】The Vampire Diaries 吸血鬼日记S06E12/【SSK字幕组】The Vampire Diaries 吸血鬼日记S06E12.ass
    

    ... 有用。


对于希腊的Windows,我创建了拉链用这种方法成功和编码CP737
ndemou

太棒了!我仔细检查了手册页,它实际上可以工作,但完全没有文档说明,zsh补全都没有此参数。
ttimasdf

2
unzip在Mac OS X中没有此选项,并且始终创建百分比编码的文件名。@javacom的unar建议很有魅力。
菲尔·克里洛夫'18

看起来像Debian特有的功能。我unzip告诉您,现在UnZip 6.00 of 20 April 2009, by Info-ZIP. Maintained by C. Spieler提供但不提供此类选项。
L29Ah

2
@ L29Ah unzipDebian 9中的My 是完全相同的版本,没有此类选项。可能是特定于Ubuntu的?
Arnie97 '19

11

在大多数POSIX文件系统上,文件名只是一系列字节,它取决于用户空间。您可以利用此优势。

  1. 首先,使用来提取档案bsdtar,因为该unzip工具似乎会破坏文件名,而bsdtar会原始提取文件名。(我正在Linux上进行测试。我想FreeBSD只是称呼它tar。)

    $ bsdtar xf gb18030.zip
    
  2. 验证诸如之类的工具iconv可以成功解码名称:

    $ find . | iconv -f gb18030 -t utf-8
    

    (请注意,这只会影响find输出,而不会影响文件本身。)

  3. 最后用于convmv将文件名转换为UTF-8:

    $ convmv -r -f gb18030 -t utf-8 --notest .
    

    (注意:我必须从CPAN安装Encode :: HanExtra以获取GB18030支持,然后手动添加use Encode::HanExtra;到/ usr / bin / convmv中,即使它应该

  4. 如果convmv不可用,请编写脚本:

    $ find . -depth | while read -r old; do
        old=./$old;
        head=${old%/*};
        tail=${old##*/};
        new=$head/$(echo "$tail" | iconv -f gb18030 -t utf-8);
        [ "$old" = "$new" ] || mv "$old" "$new";
    done
    

    (至少在Linux上,它的优点iconv是几乎始终可用,并且始终支持gb18030。)


感谢感谢调查此。我现在正在OSX上进行测试(但这确实接近FreeBSD,我认为结果会相似)。为我的问题添加评论,不能在此处编辑...
2ge

1
@ 2ge:啊,OSX实际上可能完全不同,因为HFS +在内部将文件名强制为NFD UTF-16,而不是存储字节串,因此有可能在您有机会对其进行转换之前破坏GB18030名称。
user1686

我编辑了原始问题,添加了更多评论。
2015年

是的,我在macOS Sierra上尝试过,并且bsdtar报告了很多“无法创建xxx”错误(因为父目录名称已正确输入)。必须将存档复制到Linux VPS,使用unzip -O解压缩,然后使用ssh -C将结果复制回Mac。
Chang Qian'9

10

方法1:使用Unar实用程序

sudo apt-get install unar

unar -e gb18030 gb18030.zip

方法2:使用python脚本解压缩文件(参考https://gist.github.com/usunyu/dfc6e56af6e6caab8018bef4c3f3d452#file-gbk-unzip-py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# unzip-gbk.py

import os
import sys
import zipfile
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("--encoding", help="encoding for filename, default gbk")
parser.add_argument("-l", help="list filenames in zipfile, do not unzip", action="store_true")
parser.add_argument("file", help="process file.zip")
args = parser.parse_args()
print "Processing File " + args.file

file=zipfile.ZipFile(args.file,"r");
if args.encoding:
    print "Encoding " + args.encoding
for name in file.namelist():
    if args.encoding:
        utf8name=name.decode(args.encoding)
    else:
        utf8name=name.decode('gbk')
    pathname = os.path.dirname(utf8name)
    if args.l:
        print "Filename " + utf8name
    else:
        print "Extracting " + utf8name
        if not os.path.exists(pathname) and pathname!= "":
            os.makedirs(pathname)
        data = file.read(name)
        if not os.path.exists(utf8name):
            fo = open(utf8name, "w")
            fo.write(data)
            fo.close
file.close()

示例gb18030.zip将提取以下文件

【SSK字幕组】The Vampire Diaries 吸血鬼日记S06E12
【SSK字幕组】The Vampire Diaries 吸血鬼日记S06E12/【SSK字幕组】The Vampire Diaries 吸血鬼日记S06E12.ass

2
谢谢unar方法是最无忧至少在Mac OS X
菲尔·克雷洛夫

4

在OS X上,可以使用一个名为The Unarchiver的GUI应用程序。可以使用Mac App StoreHomebrew Cask进行安装:

brew cask install the-unarchiver

当您打开带有ZIP文件的文件时,该应用程序允许您使用存档中文件名的预览来选择适当的编码。


4

7z支持带开关的字符集ID -scs,例如:

7z x -scs903 some.zip

其中903是中文简体字符集。可以在此处找到更长的字符集ID列表。


2
7z -scs开关仅选择@-defined文件列表的编码。
菲尔·克里洛夫'18

1

使用7z解压缩文件

7z x yourfile.zip

之后,请自行转换这些文件名的编码:

convmv --notest -f from_encoding -t utf-8 -r your_extracted_folder/

这对我有用。.from_encoding在我的情况下是tis-620(泰语编码),您需要找到合适的语言编码。流行的方法通常可以解决该问题,但是如果文件名仍然不可读,请尝试将from_encoding更改为其他内容,例如Windows-1252或shift-jis(日语)或其他内容,您可以使用以下命令列出可用的编码:

convmv --list
iconv --list

对我来说,这是非常简单的“如何解决”方法。


0

我只是用7zip,它设法选择了正确的编码。

(标准zip无法执行的操作)

但在Windows上通过GUI工具使用了它。也许命令行7z也将为您工作。


有一个推荐7z的答案,您的答案仅此而已。
Melebius

1
是的,现在有另一个答案推荐7z。您几乎不能指望Berry的答案会在五个月后发布的答案中“增加”。
斯科特,

@Scott,我很抱歉,我无法正确阅读英语月份的缩写。
Melebius

好。您可能想知道,如果将鼠标指针放在页面上的任何日期上(然后“悬停”在页面上),它将以数字显示日期。(至少这在计算机上有效;人们说这在电话上不能很好地使用。)而且,在问题的右下角下方,您将看到“有效的最早的投票”。这是答案排序顺序。如果单击“最旧”,则将按照从最旧到最新的顺序获得答案。
斯科特
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.