是否可以使用 PowerShell 创建 zip 存档?
23 回答
PowerShell v5.0 添加Compress-Archive
和Expand-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
与 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 存档的完整路径以及包含您要压缩的文件的目录的完整路径。
如果您前往 CodePlex 并获取PowerShell Community Extensions,您可以使用他们的write-zip
cmdlet。
自从
CodePlex 处于只读模式以准备关机
你可以去PowerShell Gallery。
采用最新 .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") ;
如前所述,完全没有功能,所以不要指望覆盖标志。
更新:请参阅下文,了解多年来对此进行扩展的其他开发人员......
安装 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"
自从最初的答案发布以来,很多事情都发生了变化。以下是一些使用Compress-Archive命令的最新示例。
用于创建新存档文件的命令,Draft.zip
,通过压缩两个文件,Draftdoc.docx
和diagram2.vsd
,由Path
参数指定。为此操作指定的压缩级别是 Optimal。
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
参数指定。为此操作指定的压缩级别是 Optimal。
Compress-Archive -LiteralPath 'C:\Reference\Draft Doc.docx', 'C:\Reference\Images\Diagram [2].vsd' -CompressionLevel Optimal -DestinationPath C:\Archives\Draft.Zip
Draft.zip
在文件夹中创建新存档文件的命令C:\Archives
。新存档文件包含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
会自动将扩展名附加到文件名。
编辑二- 这段代码是过去的丑陋丑陋的kluge。你不想要。
这将按照此处的示例使用 System.IO.Packaging.ZipPackage
压缩.\in
to的内容.\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,配置文件需要一个不受支持的调整。
下面给出另一个选择。这将压缩一个完整的文件夹并将存档写入具有给定名称的给定路径。
需要 .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)
这是 PowerShell v5 的本机解决方案,使用 cmdlet Compress-Archive
Creating Zip files using PowerShell。
另请参阅 Microsoft Docs for Compress-Archive。
示例 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()
以下是有关如何在使用 zip 存档时对其进行操作的概述(请记住之后关闭文件):
- 您可以通过指定第四个参数来压缩文件
CreateEntryFromFile(...)
。 - 创建一个条目会返回一个
ZipArchiveEntry
. 此对象允许您在之后检查压缩文件,包括让您报告.CompressedLength
、查看或更改.LastWriteTime
(需求Update
模式)等。 - 如果您稍后需要检查 ZIP 存档,您可以访问其
.Entries
属性,并使用上述方法以及查看文件名、完整路径、解压缩大小或删除文件(需要Update
模式)。 - 您可以稍后以两种方式提取存档。首先打开它,然后提取整个存档或单个条目(从
.Entries
或.GetEntry(...)
)。您也可以仅通过文件名提取存档。 - 如果您需要使用流,您可以创建一个空条目并打开其流以供之后写入。您还可以修改现有的 zip 条目(来自
.Entries
或.GetEntry(...)
),这样您就可以在内存中完成所有操作。
我鼓励您浏览文档,因为这就是我发现这一切的方式。
怎么样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()
这真的很晦涩但有效。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
}
如果有人需要压缩单个文件(而不是文件夹):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
这是工作代码,压缩源文件夹中的所有文件并在目标文件夹中创建一个 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.."
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:包含您要压缩的文件的目录的完整路径。
如果您安装了 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 不创建压缩包内的完整目录路径
这是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 4.5 的情况下压缩单个文件,从 C# 转换而来 StackOverflow答案。它使用从这里获取的更好的语法。
用法:
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()
}
}
}
我使用这个片段来检查我的数据库备份文件夹中尚未压缩的备份文件,使用 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 备份、压缩和传输这些文件。
这是从 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中用于压缩和提取目录的完整命令行命令如下:
对于压缩:
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'); }"