Ist es möglich, mit PowerShell ein Zip-Archiv zu erstellen?
Ist es möglich, mit PowerShell ein Zip-Archiv zu erstellen?
Antworten:
Wenn Sie zu CodePlex wechseln und die PowerShell-Community-Erweiterungenwrite-zip
herunterladen , können Sie deren Cmdlet verwenden.
Schon seit
CodePlex ist zur Vorbereitung des Herunterfahrens schreibgeschützt
Sie können zur PowerShell-Galerie gehen .
write-zip [input file/folder] [output file]
Eine reine PowerShell-Alternative, die mit PowerShell 3 und .NET 4.5 funktioniert (sofern Sie sie verwenden können):
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)
}
Übergeben Sie einfach den vollständigen Pfad zu dem Zip-Archiv, das Sie erstellen möchten, und den vollständigen Pfad zu dem Verzeichnis, das die Dateien enthält, die Sie komprimieren möchten.
PowerShell v5.0 fügt hinzu Compress-Archive
und Expand-Archive
Cmdlets. Die verlinkten Seiten enthalten vollständige Beispiele, aber das Wesentliche ist:
# 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
Compress-Archive
Beschreibung: "... die maximale Dateigröße, die Sie mithilfe von Compress-Archive komprimieren können, beträgt derzeit 2 GB. Dies ist eine Einschränkung der zugrunde liegenden API." Wenn Sie System.IO.Compression.ZipFile
diese Option jedoch verwenden , können Sie diese Einschränkung umgehen.
System.IO.Compression.ZipFile
. Wenn das von Ihnen verwendete .NET Framework dieses Limit nicht hat, sollte CmdLet dieses Limit nicht erreichen. Ich habe im Code verifiziert.
-OutputPath
Parameter.
Eine native Methode mit dem neuesten .NET 4.5-Framework, jedoch ohne Funktionen:
Schaffung:
Add-Type -Assembly "System.IO.Compression.FileSystem" ;
[System.IO.Compression.ZipFile]::CreateFromDirectory("c:\your\directory\to\compress", "yourfile.zip") ;
Extraktion:
Add-Type -Assembly "System.IO.Compression.FileSystem" ;
[System.IO.Compression.ZipFile]::ExtractToDirectory("yourfile.zip", "c:\your\destination") ;
Wie bereits erwähnt, völlig funktionslos. Erwarten Sie also kein Überschreibungsflag .
UPDATE: Weiter unten finden Sie weitere Entwickler, die dies im Laufe der Jahre erweitert haben ...
Installieren Sie 7zip (oder laden Sie stattdessen die Befehlszeilenversion herunter) und verwenden Sie diese PowerShell-Methode:
function create-7zip([String] $aDirectory, [String] $aZipfile){
[string]$pathToZipExe = "$($Env:ProgramFiles)\7-Zip\7z.exe";
[Array]$arguments = "a", "-tzip", "$aZipfile", "$aDirectory", "-r";
& $pathToZipExe $arguments;
}
Sie können es so nennen:
create-7zip "c:\temp\myFolder" "c:\temp\myFolder.zip"
& "C:\Program Files\7-Zip\7z.exe" a -tzip ($file.FullName+".zip") $file.FullName
Lot hat sich geändert, seit die erste Antwort veröffentlicht wurde. Hier sind einige der neuesten Beispiele mit dem Befehl Compress-Archive .
Befehl zum Erstellen einer neuen Archivdatei Draft.zip
durch Komprimieren von zwei Dateien Draftdoc.docx
und diagram2.vsd
angegeben durch den Path
Parameter. Die für diesen Vorgang angegebene Komprimierungsstufe ist Optimal.
Compress-Archive -Path C:\Reference\Draftdoc.docx, C:\Reference\Images\diagram2.vsd -CompressionLevel Optimal -DestinationPath C:\Archives\Draft.Zip
Befehl zum Erstellen einer neuen Archivdatei Draft.zip
durch Komprimieren von zwei Dateien Draft doc.docx
und Diagram [2].vsd
angegeben durch den LiteralPath
Parameter. Die für diesen Vorgang angegebene Komprimierungsstufe ist Optimal.
Compress-Archive -LiteralPath 'C:\Reference\Draft Doc.docx', 'C:\Reference\Images\Diagram [2].vsd' -CompressionLevel Optimal -DestinationPath C:\Archives\Draft.Zip
Befehl zum Erstellen einer neuen Archivdatei Draft.zip
im C:\Archives
Ordner. Die neue Archivdatei enthält alle Dateien im Ordner C: \ Reference , da im Parameter Path anstelle bestimmter Dateinamen ein Platzhalterzeichen verwendet wurde .
Compress-Archive -Path C:\Reference\* -CompressionLevel Fastest -DestinationPath C:\Archives\Draft
Befehl erstellt ein Archiv aus einem ganzen Ordner, C:\Reference
Compress-Archive -Path C:\Reference -DestinationPath C:\Archives\Draft
PowerShell hängt die .zip
Erweiterung automatisch an den Dateinamen an.
Bearbeiten Sie zwei - Dieser Code ist eine hässliche, hässliche Kluge aus alten Tagen. Du willst es nicht.
Dadurch wird der Inhalt von .\in
to .\out.zip
mit System.IO.Packaging.ZipPackage gemäß dem hier gezeigten Beispiel komprimiert
$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()
Bearbeiten: Unzuverlässig für größere Dateien, möglicherweise> 10 MB, YMMV. Etwas zu tun mit Appdomain Beweise und isoliert Lagerung. Der freundlichere .NET 4.5- Ansatz funktioniert gut mit PS v3, wollte aber in meinem Fall mehr Speicher. Um .NET 4 von PS v2, Konfigurationsdateien benötigen einen verwenden nicht unterstützten zwicken .
Geben Sie unter einer anderen Option. Dadurch wird ein vollständiger Ordner komprimiert und das Archiv in einen bestimmten Pfad mit dem angegebenen Namen geschrieben.
Benötigt .NET 3 oder höher
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)
Hier ist eine native Lösung für PowerShell v5 mit dem Cmdlet Compress-Archive
Erstellen von Zip-Dateien mit PowerShell .
Siehe auch Microsoft Docs for Compress-Archive .
Beispiel 1:
Compress-Archive `
-LiteralPath C:\Reference\Draftdoc.docx, C:\Reference\Images\diagram2.vsd `
-CompressionLevel Optimal `
-DestinationPath C:\Archives\Draft.Zip
Beispiel 2:
Compress-Archive `
-Path C:\Reference\* `
-CompressionLevel Fastest `
-DestinationPath C:\Archives\Draft
Beispiel 3:
Write-Output $files | Compress-Archive -DestinationPath $outzipfile
Für die Komprimierung würde ich eine Bibliothek verwenden (7-Zip ist gut, wie Michal vorschlägt ).
Wenn Sie 7-Zip installieren, enthält 7z.exe
das installierte Verzeichnis eine Konsolenanwendung.
Sie können es direkt aufrufen und jede gewünschte Komprimierungsoption verwenden.
Wenn Sie sich mit der DLL beschäftigen möchten, sollte dies auch möglich sein.
7-Zip ist Freeware und Open Source.
Was ist mit System.IO.Packaging.ZipPackage
?
Es würde .NET 3.0 oder höher erfordern.
#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()
über Anders Hesselbom
Warum schaut sich niemand die Dokumentation an? Es gibt eine unterstützte Methode zum Erstellen einer leeren Zip-Datei und zum Hinzufügen einzelner Dateien, die in dieselbe .NET 4.5-Bibliothek integriert sind, auf die alle verweisen.
Unten finden Sie ein Codebeispiel:
# 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()
Ich ermutige Sie in der Dokumentation zu sehen , wenn Sie irgendwelche Fragen.
Das ist wirklich dunkel, funktioniert aber. 7za.exe ist eine eigenständige Version von 7zip und ist mit dem Installationspaket verfügbar.
# 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
}
Wenn jemand eine einzelne Datei (und keinen Ordner) komprimieren muss : 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
Hier ist der Arbeitscode, der alle Dateien aus einem Quellordner komprimiert und eine Zip-Datei im Zielordner erstellt.
$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)
}
Hinweis:
ZipName: Vollständiger Pfad der Zip-Datei, die Sie erstellen möchten.
SourceDirectory: Vollständiger Pfad zum Verzeichnis mit den Dateien, die Sie komprimieren möchten.
Hier ist eine leicht verbesserte Version der Antwort von sonjz. Sie fügt eine Überschreiboption hinzu.
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)
}
Dies sollte auch zum Komprimieren einer einzelnen Datei ohne Verwendung eines temporären Ordners und mit nativem .Net 4.5 funktionieren, das aus C # aus dieser StackOverflow- Antwort konvertiert wurde . Es verwendet eine schönere Syntax von hier .
Verwendung:
ZipFiles -zipFilename output.zip -sourceFile input.sql -filename name.inside.zip.sql
Code:
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)
}
}
}
Verwenden von:
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
Unternehmen oder 7-Zip / andere separate Dienstprogramme zu verwenden. Ich mag die Using-Object
Funktion auch, obwohl ich mich ohne diese für einen kürzeren, schnellen und schmutzigen Ansatz entschieden habe.
Ich verwende dieses Snippet, um meinen Datenbanksicherungsordner auf noch nicht komprimierte Sicherungsdateien zu überprüfen, sie mit 7-Zip zu komprimieren und schließlich die *.bak
Dateien zu löschen , um Speicherplatz zu sparen. Hinweisdateien werden vor der Komprimierung nach Länge (kleinste bis größte) sortiert, um zu vermeiden, dass einige Dateien nicht komprimiert werden.
$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 }
Hier können Sie ein PowerShell-Skript überprüfen , um diese Dateien über FTP zu sichern, zu komprimieren und zu übertragen .
Falls Sie WinRAR installiert haben:
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;
}
Die Bedeutung der Argumente: afzip erstellt ein Zip-Archiv, df löscht Dateien, ep1 erstellt keinen vollständigen Verzeichnispfad innerhalb des Archivs
Hier ein vollständiges Befehlszeilenbeispiel zum Starten von cmd.exe oder von ssh oder was Sie wollen!
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');}"
Grüße
Das Laden der [System.IO.IOException]
Klasse und die Verwendung ihrer Methoden ist ein wichtiger Schritt, um unerwünschte Fehler zu unterdrücken, da es sich um eine Klasse handelt, die nicht in PowerShell enthalten ist. Erwarten Sie daher verschiedene Fehlerkontexte ohne diese Klasse.
Ich habe mein Skript auf das T fehlergesteuert, aber während der Verwendung der [System.IO.Compression.ZipFile]
Klasse wurde eine Menge zusätzlicher roter "Datei existiert" ausgegeben
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
}
}
Was ich hier mache, ist das Abfangen dieser E / A-Fehler, z. B. der Zugriff auf bereits vorhandene Dateien, das Abfangen dieses Fehlers und das Weiterleiten an eine Protokolldatei, die ich mit einem größeren Programm verwalte.
Vollständige Befehlszeilenbefehle in Windows zum Komprimieren und Extrahieren von Verzeichnissen lauten wie folgt:
Zur Komprimierung:
powershell.exe -nologo -noprofile -command "& { Add-Type -A 'System.IO.Compression.FileSystem'; [IO.Compression.ZipFile]::CreateFromDirectory('C:\Indus','C:\Indus.zip'); }"
Zum Extrahieren:
powershell.exe -nologo -noprofile -command "& { Add-Type -A 'System.IO.Compression.FileSystem';[IO.Compression.ZipFile]::ExtractToDirectory('C:\Indus.zip','C:\Indus'); }"
Der ionische Ansatz rockt:
https://dotnetzip.codeplex.com/wikipage?title=PS-Examples
unterstützt Passwörter, andere Kryptomethoden usw.
Dieses Skript iteriert alle Verzeichnisse und komprimiert jedes
Get-ChildItem -Attributes d | foreach {write-zip $ .Name "$ ($ .Name) .zip"}