如何使用PowerShell创build一个zip压缩文件?
是否有可能使用PowerShell创build一个zip存档?
如果您转到CodePlex并获取PowerShell社区扩展 ,则可以使用其write-zip
cmdlet。
一个纯Powershell的select与Powershell 3和.NET 4.5(如果你可以使用它)一起工作:
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) }
只需传入要创build的zip存档的完整path以及包含要压缩的文件的目录的完整path即可。
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
最新的.NET 4.5框架的本地方式,但完全没有function:
创build:
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") ;
如上所述,完全没有function,所以不要指望覆盖标志。
安装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"
编辑两个 – 这个代码是一个来自古代丑陋,丑陋的kluge。 你不需要它。
这将压缩.\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()
编辑: 不可靠的大文件,可能> 10MB,YMMV。 与AppDomain的证据和孤立的存储有关。 友好的.NET 4.5 方法在PS v3中很好地工作,但在我的情况下需要更多的内存。 要从PS v2使用.NET 4,configuration文件需要不受支持的 调整 。
给予另一种select。 这将压缩一个完整的文件夹,并将档案写入给定名称的path。
需要.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)
为了压缩,我会使用一个库(7-Zip就像Michalbuild议的那样 )。
如果您安装7-Zip ,安装的目录将包含控制台应用程序7z.exe
。
你可以直接调用它,并使用你想要的任何压缩选项。
如果你想与DLL进行交stream,那也应该是可能的。
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, "application/zip", [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
这是非常晦涩的,但工程。 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
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) }
这里是工作代码,压缩源文件夹中的所有文件,并在目标文件夹中创build一个压缩文件。
$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:您要创build的Zip文件的完整path。
SourceDirectory:包含要压缩的文件的目录的完整path。
我使用这个片段来检查我的数据库备份文件夹中尚未压缩的备份文件,使用7-Zip压缩它们,最后删除*.bak
文件以节省一些磁盘空间。 注意文件在压缩之前按长度sorting(从小到大),以避免某些文件未被压缩。
$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传输这些文件 。
如果你安装了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创buildzip存档,df删除文件,ep1不会在存档中创build完整的目录path
这也适用于压缩单个文件,而不使用临时文件夹,并使用原生.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() } } }
这里有一个完整的命令行示例,可以从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错误,比如访问已经存在的文件,捕获那个错误,并把它指向我正在用一个更大的程序维护的日志文件。
这个脚本迭代所有目录并且压缩每个目录
Get-ChildItem -Attributes d | foreach {write-zip $ .Name“$($ .Name).zip”}