CUBE SUGAR CONTAINER

技術系のこと書きます。

unzip で "need PK compat. v5.1 (can do v4.5)" と言われて解凍できない件

ある日、パスワードつきの ZIP ファイルを macOS 組み込みの unzip コマンドで解凍しようとしたところ、タイトルのようなエラーになった。 今回は、その対処方法と、そもそもどういったときに起こるのかについて。

結論から先に要約してしまうと、次の通り。

  • ZIP ファイルのフォーマットにはバージョンがある
  • unzip コマンドがサポートしているバージョンが不足すると、このエラーになる
  • エラーメッセージにある "PK" とはオリジナルの ZIP アーカイバの名称からきている
  • 必要なバージョンをサポートしている ZIP アーカイバを代わりに使えば解決する

使った環境は次の通り。

$ sw_vers 
ProductName:    Mac OS X
ProductVersion: 10.13.5
BuildVersion:   17F77
$ unzip | head -n 2
UnZip 6.00 of 20 April 2009, by Info-ZIP.  Maintained by C. Spieler.  Send
bug reports using http://www.info-zip.org/zip-bug.html; see README for details.
$ brew info p7zip
p7zip: stable 16.02 (bottled)
7-Zip (high compression file archiver) implementation
https://p7zip.sourceforge.io/
/usr/local/Cellar/p7zip/16.02_1 (103 files, 4.7MB) *
  Poured from bottle on 2018-07-31 at 23:22:00
From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/p7zip.rb

概要

事象としては、次のように解凍できないファイルがある。 エラーメッセージでは PK のバージョンが足りない的なことを言っている。

$ unzip greet.txt.zip 
Archive:  greet.txt.zip
   skipping: greet.txt               need PK compat. v5.1 (can do v4.5)

上記について調べたところ ZIP ファイルのフォーマットにもバージョンがあることを知った。 また、ZIP アーカイバのオリジナル実装の名前は PKZIP という名前で、上記の "PK" はそこからきているらしい。 ようするに macOS 組み込みの unzip コマンドが新しい ZIP フォーマット (v5.1) に対応していないってことのようだ。

解決策

解決策としては、組み込みの unzip の代わりに p7zip をインストールして使えば良い。

$ brew install p7zip

まあ p7zip に限らず v5.1 フォーマットをサポートしているアーカイバなら何でも良いはず。

7za コマンドに e (extract) オプションをつけて解凍する。 パスワードを確認されるのでターミナルに入力する。

$ 7za e greet.txt.zip 

7-Zip (a) [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=utf8,Utf16=on,HugeFiles=on,64 bits,4 CPUs x64)

Scanning the drive for archives:
1 file, 215 bytes (1 KiB)

Extracting archive: greet.txt.zip
--
Path = greet.txt.zip
Type = zip
Physical Size = 215

Enter password (will not be echoed):
Everything is Ok

Size:       13
Compressed: 215

今度はちゃんと解凍できた。

$ cat greet.txt
Hello, World

unzip (6.00) で解凍できないファイルの作り方

p7zip を使って unzip コマンドで解凍できないファイルの作り方についても書いておく。

とりあえず圧縮前のファイルを適当に用意する。

$ echo "Hello, World" > greet.txt

あとは最近の暗号化形式を指定してパスワードつき ZIP ファイルを作る。

$ 7za a -tzip -ppassword -mem=AES256 greet.txt.zip greet.txt

これで v5.1 フォーマットの ZIP ファイルができた。

$ file greet.txt.zip 
greet.txt.zip: Zip archive data, at least v5.1 to extract
$ unzip greet.txt.zip 
Archive:  greet.txt.zip
   skipping: greet.txt               need PK compat. v5.1 (can do v4.5)

ちなみに暗号化形式を指定しないで作ると v2.0 フォーマットの ZIP ファイルになった。

$ rm greet.txt.zip
$ 7za a -tzip -ppassword greet.txt.zip greet.txt
$ file greet.txt.zip                            
greet.txt.zip: Zip archive data, at least v2.0 to extract

これなら macOS の unzip コマンドでも解凍できる。

$ unzip greet.txt.zip
Archive:  greet.txt.zip
[greet.txt.zip] greet.txt password: 
 extracting: greet.txt

いじょう。