PowerShellでZIPファイルのコメントを読み込む

powershell7 コンピュータ
powershell7

Wikipediaでzipファイルのページを見ていたら、zipファイルの構造の情報がありました。
その中にzipファイルにコメントを埋め込む項目があり、ファイル内の位置の情報もあったのでPowerShellでコメントを読み込むスクリプトを作ってみました。

scoopでzip.exeをインストール

scoop install zip

zip.exeのバージョン

zip -h
Copyright (c) 1990-2008 Info-ZIP - Type 'zip "-L"' for software license.
Zip 3.0 (July 5th 2008). Usage:
zip [-options] [-b path] [-t mmddyyyy] [-n suffixes] [zipfile list] [-xi list]
  The default action is to add or replace zipfile entries from list, which
  can include the special name - to compress standard input.
  If zipfile and list are omitted, zip compresses stdin to stdout.
  -f   freshen: only changed files  -u   update: only changed or new files
  -d   delete entries in zipfile    -m   move into zipfile (delete OS files)
  -r   recurse into directories     -j   junk (don't record) directory names
  -0   store only                   -l   convert LF to CR LF (-ll CR LF to LF)
  -1   compress faster              -9   compress better
  -q   quiet operation              -v   verbose operation/print version info
  -c   add one-line comments        -z   add zipfile comment
  -@   read names from stdin        -o   make zipfile as old as latest entry
  -x   exclude the following names  -i   include only the following names
  -F   fix zipfile (-FF try harder) -D   do not add directory entries
  -A   adjust self-extracting exe   -J   junk zipfile prefix (unzipsfx)
  -T   test zipfile integrity       -X   eXclude eXtra file attributes
  -!   use privileges (if granted) to obtain all aspects of WinNT security
  -$   include volume label         -S   include system and hidden files
  -e   encrypt                      -n   don't compress these suffixes
  -h2  show more help

・zip.exeでzipファイルにコメントを埋め込む

zip.exe zipファイルのパス -z

.(ピリオド)で入力終了

文字コードはShift-JISのようです。

・パイプラインで文字列をコメントに埋め込む

"文字列" | zip.exe zipファイルのパス -z

こちらの文字コードはUTF8のようです。

 

以下zipファイルに埋め込まれたコメントを読み込むPowerShellスクリプト

<#
.SYNOPSIS
 ZIPファイルの読み込み
 https://ja.wikipedia.org/wiki/ZIP_(%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%83%E3%83%88)
#>

Param(
    [string]$zipPath = "H:\ps1\ReadZip\abc.zip"
)

#Echo "aaa"
#$enc = [system.Text.Encoding]::GetEncoding("Shift-JIS")
$enc = [system.Text.Encoding]::GetEncoding("UTF-8") # パイプライン用

$bytes = [System.IO.File]::ReadAllBytes($zipPath)

#$bytes[0..3] | % { echo $enc.getchars($_) }
#$bytes[0..3] | % { echo $_ }
#$localSign = [Byte[]]@(80, 75, 3, 4)
#$aaa = [Byte[]]$bytes[0..3]

$i = 0

while ($bytes[$i] -eq 80 -and $bytes[$i+1] -eq 75  -and $bytes[$i+2] -eq 3 -and $bytes[$i+3] -eq 4) 
{
    # ZIPローカルファイルヘッダ
    $compressSize = $bytes[$i+21] * 256 * 256 * 256 + $bytes[$i+20] * 256 * 256 + $bytes[$i+19] * 256 + $bytes[$i+18]
    Echo ("圧縮サイズ:{0}" -f $compressSize)

    $n = $bytes[$i+27] * 256 + $bytes[$i+26]
    Echo ("ファイル名の長さ:{0}" -f $n)

    $m = $bytes[$i+29] * 256 + $bytes[$i+28]
    Echo ("拡張フィールドの長さ:{0}" -f $m)

    $i = $i + 30 + $n + $m + $compressSize
}
while ($bytes[$i] -eq 80 -and $bytes[$i+1] -eq 75  -and $bytes[$i+2] -eq 1 -and $bytes[$i+3] -eq 2)
{
    # セントラルディレクトリエントリ
    Echo $i
    $n = $bytes[$i+29] * 256 + $bytes[$i+28]
    Echo ("ファイル名の長さ:{0}" -f $n)

    $m = $bytes[$i+31] * 256 + $bytes[$i+30]
    Echo ("拡張フィールドの長さ:{0}" -f $m)

    $k = $bytes[$i+33] * 256 + $bytes[$i+32]
    Echo ("ファイルコメントの長さ:{0}" -f $k)

    $i = $i + 46 + $n + $m + $k
} 
Echo ("{0:x}" -f $i)
if ($bytes[$i] -eq 80 -and $bytes[$i+1] -eq 75  -and $bytes[$i+2] -eq 5 -and $bytes[$i+3] -eq 6)
{
    # ZIPセントラルディレクトリの終端レコード
    $n = $bytes[$i+21] * 256 + $bytes[$i+20]
    Echo ("コメントの長さ:{0}" -f $n)

    #$str = ""
    #$bytes[($i+22)..($i+22+$n)] | % { $str += $enc.getchars($_); Write-Host $_ }
    #Echo $str
    $str = $enc.GetString($bytes[($i+22)..($i+22+$n)])
    Echo $str
}

実行結果

圧縮サイズ:3
ファイル名の長さ:7
拡張フィールドの長さ:0
40
ファイル名の長さ:7
拡張フィールドの長さ:0
ファイルコメントの長さ:0
5d
コメントの長さ:10
文字コード

zip.exeで埋め込んだコメントの文字列「文字コード」を取り出すことができました。
Windows11でPowerShell7で実行していますが、zip.exe -zでコメントは文字コードがShift-JISで扱われているようです

パイプラインで送り込むとUTF-8の文字列も埋め込むことができました。ただし、zip.exe -zではコメントを取り出すことが出来ませんでした。

PowerShellのスクリプトではコメントをバイナリで取り出して、しかるべきエンコーディング(Shift-JIS or UTF-8)で文字列に変換することで文字化けすることなく表示することが出来ました。

コメント