Mike Goldweber
Mike Goldweber

Reputation: 387

Anomoly with io.compression.zipfile in Powershell

I'm using a powershell script to automate the archiving of a directory, and its sub-directories. I'm using a very simple

    Add-Type -AssemblyName "system.io.compression.filesystem"
    [io.compression.zipfile]::CreateFromDirectory($d, $destinationFilename)

For the most part, this is doing precisely what I need it to do; but lately there is a problem with empty sub-directories. These empty sub-directories are somehow getting compressed as files, rather than directories.

  1. First, has anyone else encountered this?
  2. Is the problem related to this .Net API, or is there an enviromental issue at play?
  3. Should I use a different version of the ::CreateFromDirectory function?

Thanks for your help!

Upvotes: 0

Views: 1010

Answers (1)

Ranadip Dutta
Ranadip Dutta

Reputation: 9133

I am using this script by Bryan which does what it says and it should meet your requirement too.

There are lot of parameters which you can utilize like compression type, timestamp, confirm

# Purpose: Creates a .zip file of a file or folder.
#
# Sample: zipstuff.ps1 -target "C:\Projects\wsubi" -zip_to "C:\Users\Bryan\Desktop\wsubi" [-compression fast] [-timestamp] [-confirm]
#
# Params:
# -target: The file or folder you would like to zip.
#
# -zip_to: The location where the zip file will be created. If an old version
# exists, it will be deleted.
#
# -compression (optional): Sets the compression level for your zip file. Options:
# a. fast - Higher process speed, larger file size (default option).
# b. small - Slower process speed, smaller file size.
# c. none - Fastest process speed, largest file size.
#
# -add_timestamp (optional): Applies a timestamp to the .zip file name.
# By default, no timestamp is used.
#
# -confirm (optional): When provided, indicates that you would like to be
# prompted when the zip process is finished.
#
# |Info|

[CmdletBinding()]
Param (
  [Parameter(Mandatory=$true,Position=0)]
  [string]$target,

  [Parameter(Mandatory=$true,Position=1)]
  [string]$zip_to,

  [Parameter(Mandatory=$false,Position=2)]
  [ValidateSet("fast","small","none")]
  [string]$compression,

  [Parameter(Mandatory=$false,Position=3)]
  [bool]$timestamp,

  [Parameter(Mandatory=$false,Position=4)]
  [bool]$confirm
)

#-----------------------------------------------------------------------------#
function DeleteFileOrFolder
{ Param([string]$PathToItem)

  if (Test-Path $PathToItem)
  {
    Remove-Item ($PathToItem) -Force -Recurse;
  }
}

function DetermineCompressionLevel{
[Reflection.Assembly]::LoadFile('C:\WINDOWS\System32\zipfldr.dll')
Add-Type -Assembly System.IO.Compression.FileSystem
  $CompressionToUse = $null;

  switch($compression)
  {
    "fast" {$CompressionToUse = [System.IO.Compression.CompressionLevel]::Fastest}
    "small" {$CompressionToUse = [System.IO.Compression.CompressionLevel]::Optimal}
    "none" {$CompressionToUse = [System.IO.Compression.CompressionLevel]::NoCompression}
    default {$CompressionToUse = [System.IO.Compression.CompressionLevel]::Fastest}
  }

  return $CompressionToUse;
}

#-----------------------------------------------------------------------------#
Write-Output "Starting zip process...";

if ((Get-Item $target).PSIsContainer)
{
  $zip_to = ($zip_to + "\" + (Split-Path $target -Leaf) + ".zip");
}
else{

  #So, the CreateFromDirectory function below will only operate on a $target
  #that's a Folder, which means some additional steps are needed to create a
  #new folder and move the target file into it before attempting the zip process. 
  $FileName = [System.IO.Path]::GetFileNameWithoutExtension($target);
  $NewFolderName = ($zip_to + "\" + $FileName)

  DeleteFileOrFolder($NewFolderName);

  md -Path $NewFolderName;
  Copy-Item ($target) $NewFolderName;

  $target = $NewFolderName;
  $zip_to = $NewFolderName + ".zip";
}

DeleteFileOrFolder($zip_to);

if ($timestamp)
{
  $TimeInfo = New-Object System.Globalization.DateTimeFormatInfo;
  $CurrentTimestamp = Get-Date -Format $TimeInfo.SortableDateTimePattern;
  $CurrentTimestamp = $CurrentTimestamp.Replace(":", "-");
  $zip_to = $zip_to.Replace(".zip", ("-" + $CurrentTimestamp + ".zip"));
}

$Compression_Level = (DetermineCompressionLevel);
$IncludeBaseFolder = $false;

[Reflection.Assembly]::LoadWithPartialName( "System.IO.Compression.FileSystem" );
[System.IO.Compression.ZipFile]::CreateFromDirectory($target, $zip_to, $Compression_Level, $IncludeBaseFolder);

Write-Output "Zip process complete.";

if ($confirm)
{
  write-Output "Press any key to quit ...";
  $quit = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown");
}

Usage:

zipstuff.ps1 -target "C:\Projects\wsubi" -zip_to "C:\Users\Bryan\Desktop\wsubi" [-compression fast] [-timestamp] [-confirm]

Hope it helps.

Upvotes: 2

Related Questions