如何使用PowerShell创建zip存档?


Answers:


124

如果您转到CodePlex并获取PowerShell社区扩展,则可以使用其write-zipcmdlet。

以来

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

您可以转到PowerShell画廊


114
是的,它使用7z作为大多数压缩cmdlet的核心库。我知道,因为我实施了它;)+1
x0n

1
大声笑,x0n。我将饲料商店提供程序植入了PSCX中。不太实用,但很有趣。:)
马特·汉密尔顿

1
如果使用7z,是否可以使用密码进行压缩?
mack

1
@SemiDementedwrite-zip [input file/folder] [output file]
joshschreuder 2014年

9
Powershell 5带有一个可创建.zip的Compress-Archive cmdlet,blogs.technet.microsoft.com / heyscriptingguy / 2015/08/13 /…
Benoit Patra

255

可与PowerShell 3和.NET 4.5一起使用的纯PowerShell替代方法(如果可以使用的话):

function ZipFiles( $zipfilename, $sourcedir )
{
   Add-Type -Assembly System.IO.Compression.FileSystem
   $compressionLevel = [System.IO.Compression.CompressionLevel]::Optimal
   [System.IO.Compression.ZipFile]::CreateFromDirectory($sourcedir,
        $zipfilename, $compressionLevel, $false)
}

只需输入要创建的zip归档文件的完整路径,以及包含要压缩文件的目录的完整路径。


1
这真的需要Powershell 3.0还是.net 4.5?在我看来,PowerShell的实际功能非常轻巧,而不仅仅是.net编程。
bwerks

@bwerks在此处
上午

我一直在寻找一种仅压缩单个大文件的方法,但是显然没有针对此方法。我必须编写代码来创建一个新目录,在该目录中复制单个文件,将该目录压缩为一个新的zip文件,然后删除该目录进行清理。
鲍达德2014年

1
@宝达,看我的答案。
Dherik

应该读到我需要完整的路径。那个令人困惑的男孩!顺便说一句,这应该是公认的答案
Kolob Canyon

243

PowerShell v5.0添加Compress-ArchiveExpand-Archivecmdlet。链接的页面上有完整的示例,但要点是:

# Create a zip file with the contents of C:\Stuff\
Compress-Archive -Path C:\Stuff -DestinationPath archive.zip

# Add more files to the zip file
# (Existing files in the zip file with the same name are replaced)
Compress-Archive -Path C:\OtherStuff\*.txt -Update -DestinationPath archive.zip

# Extract the zip file to C:\Destination\
Expand-Archive -Path archive.zip -DestinationPath C:\Destination

11
PowerShell v5.0现在已经正式发布。它还配备了Windows 10
辖施耐德


2
Compress-Archive说明的第2段开始:“ ...当前可以使用Compress-Archive压缩的最大文件大小为2 GB。这是基础API的限制”。但是,如果使用,则System.IO.Compression.ZipFile可以绕过此限制。
AMissico

2
2GB的限制是从继承的System.IO.Compression.ZipFile。如果您使用的.NET框架没有此限制,则CmdLet不应达到此限制。我在代码中验证了。
TravisEz13

2
@Pramod没有-OutputPath参数。
BrainSlugs83 '18

57

具有最新.NET 4.5框架的本机方式,但完全没有功能:

创建:

Add-Type -Assembly "System.IO.Compression.FileSystem" ;
[System.IO.Compression.ZipFile]::CreateFromDirectory("c:\your\directory\to\compress", "yourfile.zip") ;

萃取:

Add-Type -Assembly "System.IO.Compression.FileSystem" ;
[System.IO.Compression.ZipFile]::ExtractToDirectory("yourfile.zip", "c:\your\destination") ;

如前所述,完全没有功能,所以不要指望覆盖标志。

更新:这些年来在此方面进行了扩展的其他开发人员,请参见下文...


为什么要使用无特征方法?
冥王星

这应该是按照发布日期和先例顺序接受的答案。至于您的最新评论-现在确实有很多方法可以做到这一点。我面临着需要此功能的问题,在PowerShell 4上,我发现的第一件事就是本机方法。在2009年,这是一个很好的问题。我仍然认为,最初提出该问题时,可能还会有进一步的研究提出。
DtechNet '18

45

安装7zip(或下载命令行版本)并使用以下PowerShell方法:

function create-7zip([String] $aDirectory, [String] $aZipfile){
    [string]$pathToZipExe = "$($Env:ProgramFiles)\7-Zip\7z.exe";
    [Array]$arguments = "a", "-tzip", "$aZipfile", "$aDirectory", "-r";
    & $pathToZipExe $arguments;
}

您可以这样称呼它:

create-7zip "c:\temp\myFolder" "c:\temp\myFolder.zip"

6
如果7zip在您的路径中,那么您只需要编写“&7z c:\ temp \ myFolder c:\ temp \ myFolder.zip”
aboy021 2013年

5
如果您不想安装它,则可以下载命令行版本。(仅查看​​7-zip的“下载”页面。)它只是一个可执行文件,命令语法相同。但是,可执行文件的名称不同。由于某种原因,它是7za.exe。我已经在许多项目上做到了这一点,从来没有让我失望过。
jpmc26 2014年

我尝试使用.net和Powershell工具太久了,直到找到立即可用的7zip路径。$ file上的简单foreach循环可以解决问题& "C:\Program Files\7-Zip\7z.exe" a -tzip ($file.FullName+".zip") $file.FullName
SebK

17

自发布初始答案以来,批次已更改。以下是一些使用Compress-Archive命令的最新示例。

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

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

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

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

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

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

Command从整个文件夹创建档案, C:\Reference

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

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


15

编辑两个 -此代码是从前的丑陋丑陋的克鲁格。你不想要。

按照此处的示例.\in.\out.zip使用System.IO.Packaging.ZipPackage 将的内容压缩为

$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()

编辑: 对于较大的文件可能不可靠,YMMV可能大于10mb。东西 与应用程序域证据和隔离存放。友好的.NET 4.5 方法可以在PS v3上很好地工作,但是在我的情况下需要更多的内存。要从PS v2使用.NET 4,配置文件需要不受支持的 tweak


ZipPackage的主要问题是它不是普通的ZIP文件,但是包含内容xml文件。请参阅:[如何避免.net的ZipPackage类中的[Content_Types] .xml-堆栈溢出](stackoverflow.com/questions/3748970/…
aaron

@aaron还有一个很好的理由不要再使用它了!您在这里遇到了“主要问题”的激烈竞争;)
noam

12

下面给出另一个选择。这将压缩一个完整的文件夹,并将归档文件以给定名称写入给定路径。

需要.NET 3或更高版本

Add-Type -assembly "system.io.compression.filesystem"

$source = 'Source path here'    
$destination = "c:\output\dummy.zip"

If(Test-path $destination) {Remove-item $destination}

[io.compression.zipfile]::CreateFromDirectory($Source, $destination)

10

这是使用cmdlet 使用PowerShell创建Zip文件的 PowerShell v5的本机解决方案Compress-Archive

另请参阅用于压缩存档的Microsoft文档

范例1:

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

范例2:

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

范例3:

Write-Output $files | Compress-Archive -DestinationPath $outzipfile

7

对于压缩,我会使用一个库(如Michal建议的那样 7-Zip很好)。

如果安装7-Zip,则安装的目录将包含7z.exe一个控制台应用程序。
您可以直接调用它并使用所需的任何压缩选项。

如果您希望使用DLL,那也应该可行。
7-Zip是免费软件和开放源代码。


2
下面是使用7拉链从Powershell的AES加密的一个示例:codeblog.theg2.net/2010/02/...
格雷格布雷

7

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()

通过Anders Hesselbom


5

为什么没人看文档呢?有一种受支持的方法,可以创建一个空的zip文件并将单个文件添加到内置到每个人都引用的同一.NET 4.5库中。

参见下面的代码示例:

# Load the .NET assembly
Add-Type -Assembly 'System.IO.Compression.FileSystem'

# Must be used for relative file locations with .NET functions instead of Set-Location:
[System.IO.Directory]::SetCurrentDirectory('.\Desktop')

# Create the zip file and open it:
$z = [System.IO.Compression.ZipFile]::Open('z.zip', [System.IO.Compression.ZipArchiveMode]::Create)

# Add a compressed file to the zip file:
[System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($z, 't.txt', 't.txt')

# Close the file
$z.Dispose()

如果您有任何疑问,建议您浏览文档


2
谢谢你,这很完美。特别是与Compress-Archive cmdlet相比,该cmdlet设计不良,并且没有在zip中指定路径的好方法。
拉斐尔·基托弗

4

这确实很晦涩,但可以。7za.exe是7zip的独立版本,可通过安装软件包获得。

# get files to be send
$logFiles = Get-ChildItem C:\Logging\*.* -Include *.log | where {$_.Name -match $yesterday} 

foreach ($logFile in $logFiles)
{
    Write-Host ("Processing " + $logFile.FullName)

    # compress file
    & ./7za.exe a -mmt=off ($logFile.FullName + ".7z") $logFile.FullName

}

4

如果有人需要压缩单个文件(而不是文件夹),请访问:http : //blogs.msdn.com/b/jerrydixon/archive/2014/08/08/zipping-a-single-file-with-powershell.aspx

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

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

<#
     .SYNOPSIS
     Creates a ZIP file that contains the specified innput file.

     .EXAMPLE
     FileZipper -sourceFile c:\test\inputfile.txt 
                -destinationFile c:\test\outputFile.zip
#> 

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
     }
}

dir $sourceFile | Add-Zip $destinationFile

此代码依赖于shell应用程序,然后猜测需要500毫秒等待它完成...我不同意它的工作原理(在大多数情况下)。但是,在每次添加压缩文件都需要一定时间(在添加大文件或使用大zip的情况下很容易复制)的每种情况下,它都会创建弹出窗口。同样,如果任何zip操作比指定的任何睡眠时间都慢,它将无法添加文件并留下弹出对话框。这对于脚本编写很糟糕。我也否决了依赖COM对象的其他答案,因为它无法解决这些陷阱。
冥王星

4

这是工作代码,从源文件夹压缩所有文件,并在目标文件夹中创建一个zip文件。

    $DestZip="C:\Destination\"
    $Source = "C:\Source\"

    $folder = Get-Item -Path $Source

    $ZipTimestamp = Get-Date -format yyyyMMdd-HHmmss;
    $ZipFileName  = $DestZip + "Backup_" + $folder.name + "_" + $ZipTimestamp + ".zip" 

    $Source

    set-content $ZipFileName ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18)) 
    # Wait for the zip file to be created.
    while (!(Test-Path -PathType leaf -Path $ZipFileName))
    {    
        Start-Sleep -Milliseconds 20
    } 
    $ZipFile = (new-object -com shell.application).NameSpace($ZipFileName)

    Write-Output (">> Waiting Compression : " + $ZipFileName)       

    #BACKUP - COPY
    $ZipFile.CopyHere($Source) 

    $ZipFileName
    # ARCHIVE

    Read-Host "Please Enter.."

4
function Zip-File
    {
    param (
    [string]$ZipName,
    [string]$SourceDirectory 

    )
       Add-Type -Assembly System.IO.Compression.FileSystem
       $Compress = [System.IO.Compression.CompressionLevel]::Optimal
       [System.IO.Compression.ZipFile]::CreateFromDirectory($SourceDirectory,
            $ZipName, $Compress, $false)
    }

注意:
ZipName:您要创建的Zip文件的完整路径。

SourceDirectory:包含要压缩的文件的目录的完整路径。


3

这是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)
}

2
您能否详细说明您的答案,并提供有关您提供的解决方案的更多说明?
abarisone 2015年

我采用了先前的答案,并通过添加覆盖选项对其进行了改进,仅此而已!
Lou O.

3

这也适用于压缩单个文件而无需使用temp文件夹和本机.Net 4.5(从此StackOverflow 答案的 C#转换而来)。它使用从此处获取的更好的语法。

用法:

ZipFiles -zipFilename output.zip -sourceFile input.sql -filename name.inside.zip.sql

码:

function ZipFiles([string] $zipFilename, [string] $sourceFile, [string] $filename)
{
    $fullSourceFile = (Get-Item -Path "$sourceFile" -Verbose).FullName
    $fullZipFile = (Get-Item -Path "$zipFilename" -Verbose).FullName

    Add-Type -AssemblyName System.IO
    Add-Type -AssemblyName System.IO.Compression
    Add-Type -AssemblyName System.IO.Compression.FileSystem

    Using-Object ($fs = New-Object System.IO.FileStream($fullZipFile, [System.IO.FileMode]::Create)) {
         Using-Object ($arch = New-Object System.IO.Compression.ZipArchive($fs, [System.IO.Compression.ZipArchiveMode]::Create)) {
             [System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($arch, $fullSourceFile, $filename)
        }
    }
}

使用:

function Using-Object
{
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [AllowEmptyString()]
        [AllowEmptyCollection()]
        [AllowNull()]
        [Object]
        $InputObject,

        [Parameter(Mandatory = $true)]
        [scriptblock]
        $ScriptBlock
    )

    try
    {
        . $ScriptBlock
    }
    finally
    {
        if ($null -ne $InputObject -and $InputObject -is [System.IDisposable])
        {
            $InputObject.Dispose()
        }
    }
}

优秀的。我一直在寻找一种无需使用该shell.application业务或7-Zip /其他单独实用程序即可压缩一个文件的方法。我也喜欢该Using-Object功能,尽管我没有使用它,但使用了一种更短,更快速的方法。
Charlie Joynt

2

我使用此代码段检查数据库备份文件夹中是否尚未压缩的备份文件,使用7-Zip压缩它们,最后删除*.bak文件以节省一些磁盘空间。注意文件在压缩前按长度(从最小到最大)排序,以避免某些文件不被压缩。

$bkdir = "E:\BackupsPWS"
$7Zip = 'C:\"Program Files"\7-Zip\7z.exe'

get-childitem -path $bkdir | Sort-Object length |
where
{
    $_.extension -match ".(bak)" -and
    -not (test-path ($_.fullname -replace "(bak)", "7z"))
} |
foreach
{
    $zipfilename = ($_.fullname -replace "bak", "7z")
    Invoke-Expression "$7Zip a $zipfilename $($_.FullName)"
}
get-childitem -path $bkdir |
where {
    $_.extension -match ".(bak)" -and
   (test-path ($_.fullname -replace "(bak)", "7z"))
} |
foreach { del $_.fullname }

在这里,您可以检查PowerShell脚本以通过FTP备份,压缩和传输这些文件


2

如果您安装了WinRAR:

function ZipUsingRar([String] $directory, [String] $zipFileName)
{
  Write-Output "Performing operation ""Zip File"" on Target ""Item: $directory Destination:"
  Write-Output ($zipFileName + """")
  $pathToWinRar = "c:\Program Files\WinRAR\WinRar.exe";
  [Array]$arguments = "a", "-afzip", "-df", "-ep1", "$zipFileName", "$directory";
  & $pathToWinRar $arguments;
}

参数的含义:afzip创建zip归档文件,df删除文件,ep1不创建归档文件中的完整目录路径


2

这里是一个完整的命令行示例,可从cmd.exe或ssh或所需的命令启动!

powershell.exe -nologo -noprofile -command "&{ Add-Type -A 'System.IO.Compression.FileSystem' [System.IO.Compression.ZipFile]::CreateFromDirectory('c:/path/to/source/folder/', 'c:/path/to/output/file.zip');}"

问候


2

正在加载 [System.IO.IOException]类并使用其方法是抑制不必要错误的重要步骤,这是因为它不是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错误,例如访问已存在的文件,捕获该错误并将其定向到我正在使用大型程序维护的日志文件中。


2

Windows中用于压缩和提取目录的完整命令行命令如下:

  • 对于压缩:

    powershell.exe -nologo -noprofile -command "& { Add-Type -A 'System.IO.Compression.FileSystem'; [IO.Compression.ZipFile]::CreateFromDirectory('C:\Indus','C:\Indus.zip'); }"
  • 提取:

    powershell.exe -nologo -noprofile -command "& { Add-Type -A 'System.IO.Compression.FileSystem';[IO.Compression.ZipFile]::ExtractToDirectory('C:\Indus.zip','C:\Indus'); }"


-4

该脚本迭代所有目录并压缩每个目录

Get-ChildItem-属性d | foreach {write-zip $ .Name“ $($ .Name).zip”}


1
与7年问题相关的唯一部分是“ write-zip”,这是2009
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.