今日の知見

Toshが諸々で得た知見を雑に書きます。

9日目: VBScript で zip 圧縮

2018-08-07 追記: どうやら ShellApplication から zip ファイルを処理することは想定されていないようです。
Tosh の周りでは後述の処理で問題なく圧縮ができておりますが、想定しない事象が発生する可能性があるため、実行は自己責任でお願いできますと幸いです。
詳細は下記リンクにて。
https://support.microsoft.com/ja-jp/help/2679832

(「想定しない挙動」がどんなものか興味がありますので、リンク先に掲載されている以外の事象が発生しましたらコメント頂ければと。)

ご挨拶

こんにちは、Tosh でございます。
派遣先より失礼致します。
平日帰宅してからだと続けられそうにないので、仕事中のテンションを利用して(ドタバタしてなければ)休憩中に書いてしまおうというアレですね。
思い切り私用なんですが、仕事の生産性にかかわることなので許してください何でもしますから!()

VBScript で zip 圧縮

まずはサンプルコードをば。
VBScript のお作法は何も理解してないので変数名とかすごく適当なんですが、何卒何卒。

' 
' zip 圧縮
' 
Function zipCompress(ByVal fileName)
  ' ファイルシステム
  Dim fso: Set fso = CreateObject("Scripting.FileSystemObject")

  ' 拡張子を取る
  Dim withoutExt: withoutExt = Left(fileName, InStr(fileName, ".") - 1)
  
  ' zip ファイルを作成
  Dim zipFileName: zipFileName = withoutExt & ".zip"
  Dim zipFile: Set zipFile = fso.OpentextFile(zipFileName, 2, true)
  zipFile.Write Chr(&H50) & Chr(&H4B) & Chr(&H5) & Chr(&H6) & String(18, Chr(0))
  zipFile.Close
  Set zipFile = Nothing
  
  ' zip ファイルに 元のファイルを入れる
  Dim wsh: Set wsh = CreateObject("Shell.Application")
  Dim zipFileSh: Set zipFileSh = wsh.NameSpace(fso.GetAbsolutePathName(zipFileName))
  Dim parentFolderPath: parentFolderPath = fso.GetAbsolutePathName(fso.GetParentFolderName(fileName))
  zipFileSh.CopyHere wsh.NameSpace(parentFolderPath).ParseName(fso.getFileName(fileName))
  
  ' 圧縮が終わるまで待ち合わせ
  Do Until zipFileSh.Items().Count = 1: WScript.Sleep 100: Loop
  
  ' 元のファイルを削除
  fso.DeleteFile fileName
  
  Set fso = Nothing

  zipCompress = true
End Function

流れとしてはコメントの通りで、今一度下記にまとめます。

  1. ファイル名から拡張子を除いたものを抜き出す
  2. 1.の名前で空の zip ファイルを作成する
  3. 2.の zip ファイルに元のファイルを入れる
  4. 元のファイルを削除する(オプション化すべき?)

ではでは、簡単に解説をば。

1. ファイル名から拡張子を除いたものを抜き出す

単に切り出しているだけなので省略。

2. 1.の名前で空の zip ファイルを作成する

ファイル作成自体は FileSystemObject によるテキストファイル出力とほとんど変わらないと思います。 気を付けて頂きたいのは下記のおまじないですね。
どうやら zip ファイルの先頭は下記のバイナリになっているようです。 この部分が理解できれば他の言語でも zip 圧縮を実装できる?

  zipFile.Write Chr(&H50) & Chr(&H4B) & Chr(&H5) & Chr(&H6) & String(18, Chr(0))

3. 2.の zip ファイルに元のファイルを入れる

VBScript の組み込み関数ではどうしようもないみたいなので、ShellApplication を呼び出してごにょごにょやってます。
具体的には、下記のようなことを雰囲気でやっております。

  1. ShellApplication のカレントパスをファイルのパスに指定
  2. 親フォルダのパスを取得
  3. 1.と2.を使用して zip ファイルに投入

それぞれの関数の詳細は省かせて頂きますm(_ _)m

4. 元のファイルを削除する

FileSystemObject の関数を呼び出しているだけなので省略

ではでは、今日はこの辺で。