Compress files in a folder to a zip file using PS

I have the following scripts to compress a folder (all files in a folder) in a zip file:

set-content $zipFileName ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18)) $ZipFile = (new-object -com shell.application).NameSpace($zipFileName) Get-ChildItem $folder | foreach {$zipFile.CopyHere($_.fullname)} 

where $ folder = "C: \ Test" and $ zipFileName = "C: \ data \ test.zip" as an example

It works fine if "C: \ Test" does not contain empty subfolders and seems to work recursively to compress all the files in the subfolders. I really like the simpler line of script. For example:

 C:\Test file1.dat file2.dat Test-Sub File21.bat .... 

However, in one case, I got an error. I find that if there is an empty folder such as "C: \ Test \ EmptySub",

 C:\Test file1.dat file2.dat Test-Sub File21.bat .... EmptySub AnotherSub file31.sp1 ... 

The script will create an error. I tried the following scripts:

 Get-ChildItem $files -Recurse | foreach { if (!$_.PSIsContainer) {$zipFile.CopyHere($_.fullname)}} 

This does not work properly. It just skips all subfolders. Not sure if there is a filter or suggestion to skip all empty subfolders?

Updated . Based on the suggestions, I tried. My problem is not resolved. Here is an update of my question. First, I updated the scripts above to show how the $ zipFile object is created. Secondly, I have suggested codes:

 Get-ChildItem $files | ? {-not ($_.PSIsContainer -eq $True -and $_.GetFiles().Count -eq 0) } | % {$zipfile.CopyHere($_.fullname)} 

I tried updating on my WindowsXP, it works fine with empty subfolders. However, these same codes do not work in Windows 2003 Server. The following is the error message:

[Window title] Compressed (compressed) folder error

[Content] File not found or not readable.

[OK]

Not sure if this object of type PK works on a Windows 2003 server or if there are other settings for the object.

+7
source share
3 answers

You can detect empty directories by checking for empty returns from get-childitem. For example, this will return a list of empty directories

 dir | where{$_.PSIsContainer -and -not (gci $_)} 

Although in your case you want the opposite:

 Get-ChildItem $files | where{-not ($_.PSIsContainer -and -not (gci $_))} | foreach {$zipfile.CopyHere($_.fullname)}} 
+3
source

Your code works recursively in the sense that you get some kind of child (including folders). If you intend to exclude an empty folder, you should filter them out:

Try using one liner:

  gci $ folder | `
 ?  {-not ($ _. PSIsContainer -eq $ True -and $ _. GetFiles (). Count -eq 0)} | `
 % {$ zipfile.CopyHere ($ _. fullname)}
+2
source

Here is the function I created for zip files. The reason you get a read error is because .CopyHere is an asynchronous copy process, so my script checks the file in the zip file before moving on to the next file for zip:

 function Out-ZipFile ([string]$path) { try { $files = $input if ($path.StartsWith(".\")) { $path=$path.replace(".\","$($pwd)\") } if (-not $path.Contains("\")) { $path="$($pwd)\$($path)" } if (-not $path.EndsWith('.zip')) {$path += '.zip'} if (-not (test-path $path)) { set-content $path ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18)) } $ZipFile = (new-object -com shell.application).NameSpace($path) $files | % { $FileName = $_.name "Adding $FileName to $path"; $ZipFile.CopyHere($_.fullname); While (($ZipFile.Items() | where { $_.Name -like $FileName }).Size -lt 1) { Start-Sleep -m 100 }; } } catch { write-output "Error Encountered: `n$_" return $_ throw } } 
+1
source

All Articles