# Zipping only files using powershell

I'm trying to zip all the files in a single directory to a different folder as part of a simple backup routine.

The code runs ok but doesn't produce a zip file:

$srcdir = "H:\Backup"$filename = "test.zip"
$destpath = "K:\"$zip_file = (new-object -com shell.application).namespace($destpath + "\"+$filename)
$destination = (new-object -com shell.application).namespace($destpath)

$files = Get-ChildItem -Path$srcdir

foreach ($file in$files)
{
$file.FullName; if ($file.Attributes -cne "Directory")
{
$destination.CopyHere($file, 0x14);
}
}

Any ideas where I'm going wrong?

-
Simply adding .zip to the end of a file doesn't make it a .zip archive. Are you using PowerShell 2.0 or 3.0? If you're using 3.0, it's a heck of a lot easier. –  MDMarra Dec 7 '12 at 15:53
@MDMarra - Yes, powershell 3 (developed on Win7, deployed on Server 2003), isn't that what the "-com shell.application" does? Or have I messed that up? –  SteB Dec 7 '12 at 15:58
See the bottom of this answer for how to do this in PS3 –  MDMarra Dec 7 '12 at 16:13
@MDMarra - I now get a "make sure that the assembly containing this type is loaded." error, I've tried "[System.AppDomain]::CurrentDomain.GetAssemblies()" but can't see a compression dll –  SteB Dec 7 '12 at 16:27
Sorry, do you have .NET 4.5 installed? It's actually not a native PS3 thing, but rather a .NET 4.5 thing. My mistake for assuming you'd have both installed. –  MDMarra Dec 7 '12 at 16:30

This works in V2, should work in V3 too:

$srcdir = "H:\Backup"$zipFilename = "test.zip"
$zipFilepath = "K:\"$zipFile = "$zipFilepath$zipFilename"

#Prepare zip file
if(-not (test-path($zipFile))) { set-content$zipFile ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18)) (dir$zipFile).IsReadOnly = $false }$shellApplication = new-object -com shell.application
$zipPackage =$shellApplication.NameSpace($zipFile)$files = Get-ChildItem -Path $srcdir | where{!$_.PSIsContainer}

foreach($file in$files) {
$zipPackage.CopyHere($file.FullName)
#using this method, sometimes files can be 'skipped'
#this 'while' loop checks each file is added before moving to the next
while($zipPackage.Items().Item($file.name) -eq $null){ Start-sleep -seconds 1 } } - That looked good, but when I tried it nothing happened. I didn't get a zip file but I also didn't get any errors. Could you expand on what the Set-Content and ReadOnly = false lines do? – SteB Dec 10 '12 at 9:47 The set-content line adds the file header and creates a 0 byte file, ReadOnly =$false ensures we can copy files into the file. –  nimizen Dec 10 '12 at 10:09
I've updated my answer - the $zipFilepath &$zipFilename weren't being joined correctly. –  nimizen Dec 10 '12 at 10:38
Sorry, it was my fault, I'd accidentally changed it to Test-Path-Path! That works great now. –  SteB Dec 10 '12 at 10:58

I discovered 2 additional ways to do this and am including them for reference:

Using the .Net framework 4.5 (as suggested by @MDMarra):

$src_folder = "h:\backup"$destfile = "k:\test.zip"
$compressionLevel = [System.IO.Compression.CompressionLevel]::Optimal$includebasedir = $false [System.IO.Compression.ZipFile]::CreateFromDirectory($src_folder, $destfile,$compressionLevel, $includebasedir) This worked great on my Win7 development machine and is probably the best way to do this, but .Net 4.5 is only supported on the Windows Server 2008 (or later), my deployment machine is Windows Server 2003. Using a command-line zip tool: function create-zip([String]$aDirectory, [String] $aZipfile) { [string]$PathToZipExe = "K:\zip.exe";
& $PathToZipExe "-r"$aZipfile \$aDirectory;