是否可以使用PowerShell创建zip存档?


当前回答

编辑二——这段代码是一个非常丑陋的旧代码。你不会想要的。

这将使用system . io . package . zippackage将。\in文件的内容压缩为。\out.zip

$zipArchive = $pwd.path + "\out.zip"
[System.Reflection.Assembly]::Load("WindowsBase,Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")
$ZipPackage=[System.IO.Packaging.ZipPackage]::Open($zipArchive,
  [System.IO.FileMode]"OpenOrCreate", [System.IO.FileAccess]"ReadWrite")
$in = gci .\in | select -expand fullName
[array]$files = $in -replace "C:","" -replace "\\","/"
ForEach ($file In $files)
{
   $partName=New-Object System.Uri($file, [System.UriKind]"Relative")
   $part=$ZipPackage.CreatePart($partName, "application/zip",
      [System.IO.Packaging.CompressionOption]"Maximum")
   $bytes=[System.IO.File]::ReadAllBytes($file)
   $stream=$part.GetStream()
   $stream.Write($bytes, 0, $bytes.Length)
   $stream.Close()
}
$ZipPackage.Close()

编辑:不可靠的大文件,可能>10mb, YMMV。与appdomain证据和隔离存储有关。更友好的。net 4.5方法在PS v3上工作得很好,但在我的情况下需要更多的内存。要从PS v2使用. net 4,配置文件需要一个不受支持的调整。

其他回答

下面是sonjz回答的一个稍微改进的版本,它增加了一个覆盖选项。

function Zip-Files(
        [Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$false)]
        [string] $zipfilename,
        [Parameter(Position=1, Mandatory=$true, ValueFromPipeline=$false)]
        [string] $sourcedir,
        [Parameter(Position=2, Mandatory=$false, ValueFromPipeline=$false)]
        [bool] $overwrite)

{
   Add-Type -Assembly System.IO.Compression.FileSystem
   $compressionLevel = [System.IO.Compression.CompressionLevel]::Optimal

    if ($overwrite -eq $true )
    {
        if (Test-Path $zipfilename)
        {
            Remove-Item $zipfilename
        }
    }

    [System.IO.Compression.ZipFile]::CreateFromDirectory($sourcedir, $zipfilename, $compressionLevel, $false)
}

自最初的答案发布以来,很多事情都发生了变化。下面是一些使用Compress-Archive命令的最新示例。

命令通过压缩Draftdoc.docx和diagram2两个文件来创建新的归档文件Draft.zip。vsd,由Path参数指定。为此操作指定的压缩级别为“最佳”。

Compress-Archive -Path C:\Reference\Draftdoc.docx, C:\Reference\Images\diagram2.vsd -CompressionLevel Optimal -DestinationPath C:\Archives\Draft.Zip

命令通过压缩Draft doc.docx和Diagram[2]这两个文件来创建新的归档文件Draft.zip。vsd,由LiteralPath参数指定。为此操作指定的压缩级别为“最佳”。

Compress-Archive -LiteralPath 'C:\Reference\Draft Doc.docx', 'C:\Reference\Images\Diagram [2].vsd'  -CompressionLevel Optimal -DestinationPath C:\Archives\Draft.Zip

命令在C:\Archives文件夹中创建新的归档文件Draft.zip。新的归档文件包含C:\Reference文件夹中的每个文件,因为在Path参数中使用通配符代替了特定的文件名。

Compress-Archive -Path C:\Reference\* -CompressionLevel Fastest -DestinationPath C:\Archives\Draft

命令从整个文件夹C:\Reference创建一个存档

Compress-Archive -Path C:\Reference -DestinationPath C:\Archives\Draft

PowerShell自动将.zip扩展名附加到文件名。

如果您前往CodePlex并获取PowerShell社区扩展,您可以使用他们的write-zip cmdlet。

CodePlex处于只读模式,准备关闭

你可以去PowerShell画廊。

System.IO.Packaging.ZipPackage呢?

它需要。net 3.0或更高版本。

#Load some assemblys. (No line break!)
[System.Reflection.Assembly]::Load("WindowsBase, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")

#Create a zip file named "MyZipFile.zip". (No line break!)
$ZipPackage=[System.IO.Packaging.ZipPackage]::Open("C:\MyZipFile.zip",
   [System.IO.FileMode]"OpenOrCreate", [System.IO.FileAccess]"ReadWrite")

#The files I want to add to my archive:
$files = @("/Penguins.jpg", "/Lighthouse.jpg")

#For each file you want to add, we must extract the bytes
#and add them to a part of the zip file.
ForEach ($file In $files)
{
   $partName=New-Object System.Uri($file, [System.UriKind]"Relative")
   #Create each part. (No line break!)
   $part=$ZipPackage.CreatePart($partName, "",
      [System.IO.Packaging.CompressionOption]"Maximum")
   $bytes=[System.IO.File]::ReadAllBytes($file)
   $stream=$part.GetStream()
   $stream.Write($bytes, 0, $bytes.Length)
   $stream.Close()
}

#Close the package when we're done.
$ZipPackage.Close()

通过安德斯·赫塞尔博姆

加载[System.IO.]类,并使用它的方法是抑制不必要错误的重要步骤,因为它不是PowerShell的原生类,所以如果没有它,将会出现各种错误上下文。

我错误地控制了我的脚本到T,但在使用[System.IO.Compression]时得到了很多额外的红色“文件存在”输出。ZipFile)类

function zipFiles(
    [Parameter(Position=0, Mandatory=$true]
    [string] $sourceFolder,
    [Parameter(Position=1, Mandatory=$true]
    [string]$zipFileName,
    [Parameter(Position=2, Mandatory=$false]
    [bool]$overwrite)

{   
Add-Type -Assembly System.IO
Add-Type -Assembly System.IO.Compression.FileSystem

$compressionLevel = [System.IO.Compression.CompressionLevel]::Optimal

$directoryTest = (Test-Path $dailyBackupDestFolder)
$fileTest = (Test-Path $zipFileName)

if ( $directoryTest -eq $false) 
{ 
    New-Item -ItemType Directory -Force -Path $dailyBackupDestFolder 
}

     if ( $fileTest -eq $true)
     {
           if ($overwrite -eq $true ){Remove-Item $zipFileName}
     }   


    try
    {
         [System.IO.Compression.ZipFile]::CreateFromDirectory($sourceFolder,$zipFileName,$compressionLevel)       

    }
    catch [System.IO.IOException] 
    {
       Write-Output ($dateTime + ' | ' + $_.Exception.Message ) | Out-File $logFile -append -force 
    }
} 

我在这里所做的是捕获这些IO错误,例如访问已经存在的文件,捕获该错误并将其指向我正在使用更大的程序维护的日志文件。