如何创建一个压缩档案与PowerShell?

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

370928 次浏览

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

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

你可以去PowerShell画廊

这很晦涩,但很有效。7 za.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


}

对于压缩,我会使用一个库(7-Zip很好,像米甲说)。

如果你安装了7 - zip,安装目录将包含7z.exe,这是一个控制台应用程序 你可以直接调用它,并使用任何你想要的压缩选项

如果您希望使用DLL,这也应该是可能的 7-Zip是免费的开源软件

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

通过安德斯Hesselbom

安装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"

我使用这个片段来检查我的数据库备份文件夹的备份文件尚未压缩,使用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备份、压缩和传输这些文件

编辑两个 -这个代码是一个丑陋的,丑陋的克鲁格从过去的日子。你不会想要的。

这将使用System.IO.Packaging.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,配置文件需要不支持的 调整

一个与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归档文件的完整路径,以及包含您想要压缩的文件的目录的完整路径。

最新。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") ;

如前所述,完全没有特征,所以不要期望有覆盖标志。

更新:下面是其他开发者多年来在此基础上扩展的内容。

如果你安装了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不创建归档内的完整目录路径

PowerShell v5.0增加了Compress-ArchiveExpand-Archive cmdlet。链接页面有完整的例子,但它的要点是:

# 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

如果有人需要压缩单个文件(而不是文件夹):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

下面是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)
}

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

要求。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)

下面是工作代码,压缩源文件夹中的所有文件,并在目标文件夹中创建一个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.."

这也可以在不使用临时文件夹的情况下压缩单个文件,并使用原生的。net 4.5,从c#转换到这个StackOverflow 回答。它使用了来自在这里的更好的using语法。

用法:

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()
}
}
}
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)
}
< p >注意:< br > ZipName:要创建的Zip文件的完整路径

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

这里有一个完整的命令行示例,可以从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');}"

问候

加载[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错误,例如访问已经存在的文件,捕获该错误并将其指向我正在使用更大的程序维护的日志文件。

Windows下压缩解压目录的完整命令行如下:

  • < p >压缩:

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

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

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

参见微软文档 Compress-Archive . < / p >

示例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

为什么没人看文档?每个人都引用的. net 4.5库允许您做任何想做的事情,包括创建空ZIP并向其中添加单个文件。

请看下面的代码示例:

# Load the .NET assembly
Add-Type -Assembly 'System.IO.Compression'
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()

下面是一个关于如何操作压缩文件的概述(记住之后要关闭文件):

我鼓励你浏览文档,因为这是我如何找到所有这些。

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

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

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

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

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: \参考文件夹中的每个文件,因为在路径参数中使用了通配符来代替特定的文件名。

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

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

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

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

旧线程,但仍然,我到了这里:)

这不是最初问题的答案,但也许有人会发现如何用PS创建ZipArchive对象是有用的。

# Example, if you have like I have a $myByteArray byte[] with the compressed data:
Add-Type -AssemblyName System.IO.Compression.FileSystem


# Fixed length stream:
$strm = New-Object -TypeName System.IO.MemoryStream -ArgumentList @(, $myByteArray);


# Create ZipArchive object
$arch = [System.IO.Compression.ZipArchive]::new($strm);


# List entries
$arch.Entries