Zip and Unzip File in Powershell 4

2019-04-29 02:44发布

问题:

I am using Windows Server 2012 R2 (64 bit). I have powershell version 4 available in it. I am trying to zip and unzip files. When I try Write-Zip command, it throws me following error:

Write-Zip : The term 'Write-Zip' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.

What should I do to fix it? Do I need to install zip/winrar in the server? Or is there any other command do zip/unzip files?

回答1:

Write-Zip seems to be part of http://pscx.codeplex.com/ that require a separate installation before you can use it.

However, if you just want to create a Zip archive from a folder, you could just run

$source = "c:\temp\source"
$archive = "c:\temp\archive.zip"

Add-Type -assembly "system.io.compression.filesystem"
[io.compression.zipfile]::CreateFromDirectory($source, $archive)

This utilizes the CreateFromDirectory method from the .NET Framework class ZipFile. It creates a zip archive from the files located inside the $source folder and creates an archive as defined in the $archive variable. Note, ZipFile class was introduced in .NET Framework 4.5



回答2:

You can use custom powershell object New-Object -ComObject Shell.Application and copy the file with flags to unzip.

$filePath = "foo.zip"
$shell = New-Object -ComObject Shell.Application
$zipFile = $shell.NameSpace($filePath)
$destinationFolder = $shell.NameSpace("C:\Program Files\WindowsPowerShell\Modules")

$copyFlags = 0x00
$copyFlags += 0x04 # Hide progress dialogs
$copyFlags += 0x10 # Overwrite existing files

$destinationFolder.CopyHere($zipFile.Items(), $copyFlags)

Credit source https://github.com/hashicorp/best-practices/blob/master/packer/scripts/windows/install_windows_updates.ps1#L12-L22

This does not work with windows 'core' edition. If possible, upgrade to powershell 5 and use Expand Archive since it is much simpler.



回答3:

If you can upgrade to PowerShell V5 (https://www.microsoft.com/en-us/download/details.aspx?id=50395), it has them natively. https://richardspowershellblog.wordpress.com/2014/10/25/powershell-5-zip-and-unzip/

For PowerShell version 4, you may be able to use this search http://www.powershellgallery.com/items?q=zip&x=0&y=0. This also looks to do what you are looking for: https://www.powershellgallery.com/packages/Microsoft.PowerShell.Archive/1.0.1.0

To install the modules, you need to type:

install-module -name <module name>
  • powershellgallery.com is a free to upload site. Please check and understand module before running it.

Hope this helps. Thanks, Tim.



回答4:

Write-Zip installation could have been performed incorrectly. An incorrect manual edit of the environment parameter PSModulePath may cause it:

Bad (original) value:

PSModulePath = %SystemRoot%\system32\WindowsPowerShell\v1.0\Modules\;C:\Program Files (x86)\PowerShell Community Extensions\Pscx3\;C:\Program Files\Intel\

Good value (which fixed the problem):

PSModulePath = C:\Program Files (x86)\PowerShell Community Extensions\Pscx3\;%SystemRoot%\system32\WindowsPowerShell\v1.0\Modules\;C:\Program Files\Intel\


回答5:

Should work under PS4. SeeAdd-Zip and New-Zipfunctions

[CmdletBinding()]
Param(
 [Parameter(Mandatory=$True)]
 [ValidateScript({Test-Path -Path $_ })]
 [string]$sourceDirectory,

 [Parameter(Mandatory=$True)]
 [ValidateScript({-not(Test-Path -Path $_ -PathType Leaf)})]
 [string]$destinationFile,

 [Parameter(Mandatory=$True)]
 [int]$noOlderThanHours
 ) 

 function New-Zip
 { 
     param([string]$zipfilename)
     set-content $zipfilename ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18))
     (dir $zipfilename).IsReadOnly = $false
 }

 function Add-Zip
 {
    param([string]$zipfilename) 

    if(-not (test-path($zipfilename)))
    {
      set-content $zipfilename ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18))
      (dir $zipfilename).IsReadOnly = $false    

    }

    $shellApplication = new-object -com shell.application
    $zipPackage = $shellApplication.NameSpace($zipfilename)


      foreach($file in $input) 
      { 
          $zipPackage.CopyHere($file.FullName)
          Start-sleep -milliseconds 500
      }
 }

$oldest = (Get-Date) - (New-TimeSpan -Hours $noOlderThanHours)

$filesToZip = dir $sourceDirectory -Recurse | Where-Object {$_.lastwritetime -gt $oldest}

 Write-Host Going to zip following files 

 $filesToZip | foreach {Write-Host $_.FullName}



$filesToZip| Add-Zip $destinationFile