linux - 为什么 UnZip 提取最后一个串联的 ZIP?

标签 linux unix unzip

我发现以下行为出乎意料:

$ mkdir tmp && cd tmp/
$ for example in a b c ; do echo $example > $example.txt ; done
$ for file in `ls *` ; do zip $file.zip $file ; done
$ cat a.txt.zip b.txt.zip c.txt.zip > concatenated.zip
$ unzip concatenated.zip -d output
$ ls output/
c.txt                                     # unexpected

另一方面,p7zip 是这样做的:

$ rm -r output/
$ 7z x concatenated.zip -ooutput/
$ ls output/
a.txt

为什么 UnZip 会提取最后一个串联的 ZIP?是否从EOF开始向后遍历,直到找到PK文件签名?

最佳答案

Does it traverse backwards from EOF until it finds the PK file signature?

是的。以下是 unzip 将执行的操作:

  • 在 zip 文件末尾查找“中央目录记录末尾”(EOCD)
  • 阅读记录并按照“中心目录开始的偏移量”
  • 读取中央目录(它包含存档中每个条目的列表)
  • 读取每个条目并遵循“本地 header 的相对偏移量”
  • 读取带有数据的本地 header 并提取它

在你的情况下,你只会找到最后一个偏移量错误的 EOCD(你在前面添加了字节)。这就是为什么 unzip 告诉您:

warning [concatenated.zip]:  324 extra bytes at beginning or within zipfile
  (attempting to process anyway)

它找到c.txt.zip 的中心目录,只看到一个条目(c.txt),只提取一个文件。

考虑到 zip 文件的结构,我会说这是合乎逻辑的事情。自解压 zip 文件使用此方法:文件以二进制文件开头以提取自身并以实际 zi​​p 内容结束(参见 unzipsfxzip -A)。

如果文件开始像 zip 文件,看起来 7z 会从末尾开始尝试:

# not a.txt.zip, but a.txt
$ cat a.txt b.txt.zip c.txt.zip > prepended.zip
# fix offset
$ zip -A prepended.zip

$ unzip -l prepended.zip 
Archive:  prepended.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
        2  2016-11-22 20:29   c.txt
---------                     -------
        2                     1 file


$ 7z l prepended.zip 
[...]
Path = prepended.zip
Warning: The archive is open with offset
Type = zip
Physical Size = 326
Embedded Stub Size = 164

   Date      Time    Attr         Size   Compressed  Name
------------------- ----- ------------ ------------  ------------------------
2016-11-22 20:29:05 .....            2            2  c.txt
------------------- ----- ------------ ------------  ------------------------
2016-11-22 20:29:05                  2            2  1 files

注意 zip -A 来修复偏移量:

The -A option tells zip to adjust the entry offsets stored in the archive to take into account this "preamble" data.

我不知道您要达到什么目的,但连接 zip 文件可能不是最简单的方法(将它们解压回来并不容易)。

关于linux - 为什么 UnZip 提取最后一个串联的 ZIP?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40748141/

相关文章:

linux - 如何在终端中记住多个选项卡的 session ? (类似于 FF session 管理器)

Bash 解压文件并在名称中添加时间戳

python 解压缩——非常慢?

python - 行为不端的python sys脚本

python - Windows 与 Linux 文本文件读取

Linux 驱动程序 - 与用户空间共享一个 WaitHandle (-like)

c - APUE :how to print something alternately in two process?

linux - 符号链接(symbolic link)背后有什么?

c++ - 对 mmap 和 munmap 的 undefined reference

php - 使用 PHP 解压缩较大的文件