È possibile creare un archivio zip usando PowerShell?
È possibile creare un archivio zip usando PowerShell?
Risposte:
Se vai su CodePlex e acquisisci le estensioni della community di PowerShell , puoi utilizzare il loro write-zip
cmdlet.
Da
CodePlex è in modalità di sola lettura in preparazione all'arresto
puoi andare alla Galleria di PowerShell .
write-zip [input file/folder] [output file]
Una pura alternativa a PowerShell che funziona con PowerShell 3 e .NET 4.5 (se puoi usarlo):
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)
}
Basta passare il percorso completo all'archivio zip che si desidera creare e il percorso completo alla directory contenente i file che si desidera comprimere.
PowerShell v5.0 aggiunge Compress-Archive
e Expand-Archive
cmdlet. Le pagine collegate hanno esempi completi, ma l'essenza è:
# 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
descrizione: "... la dimensione massima del file che è possibile comprimere utilizzando Compress-Archive è attualmente di 2 GB. Questa è una limitazione dell'API sottostante" Tuttavia, se si utilizza System.IO.Compression.ZipFile
è possibile ignorare questa limitazione.
System.IO.Compression.ZipFile
. Se il framework .NET in uso non ha questo limite, CmdLet non dovrebbe raggiungere questo limite. Ho verificato nel codice.
-OutputPath
parametro.
Un modo nativo con l'ultimo framework .NET 4.5, ma interamente privo di funzionalità:
Creazione:
Add-Type -Assembly "System.IO.Compression.FileSystem" ;
[System.IO.Compression.ZipFile]::CreateFromDirectory("c:\your\directory\to\compress", "yourfile.zip") ;
Estrazione:
Add-Type -Assembly "System.IO.Compression.FileSystem" ;
[System.IO.Compression.ZipFile]::ExtractToDirectory("yourfile.zip", "c:\your\destination") ;
Come accennato, totalmente privo di funzionalità, quindi non aspettarti un flag di sovrascrittura .
AGGIORNAMENTO: Vedi sotto per altri sviluppatori che si sono espansi su questo nel corso degli anni ...
Installa 7zip (o scarica invece la versione da riga di comando) e usa questo metodo 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;
}
Puoi chiamarlo così:
create-7zip "c:\temp\myFolder" "c:\temp\myFolder.zip"
& "C:\Program Files\7-Zip\7z.exe" a -tzip ($file.FullName+".zip") $file.FullName
Il lotto è cambiato da quando è stata pubblicata la risposta iniziale. Ecco alcuni degli ultimi esempi usando il comando Compress-Archive .
Comando per creare un nuovo file di archivio, Draft.zip
comprimendo due file Draftdoc.docx
e diagram2.vsd
, specificato dal Path
parametro. Il livello di compressione specificato per questa operazione è ottimale.
Compress-Archive -Path C:\Reference\Draftdoc.docx, C:\Reference\Images\diagram2.vsd -CompressionLevel Optimal -DestinationPath C:\Archives\Draft.Zip
Comando per creare un nuovo file di archivio, Draft.zip
comprimendo due file Draft doc.docx
e Diagram [2].vsd
, specificato dal LiteralPath
parametro. Il livello di compressione specificato per questa operazione è ottimale.
Compress-Archive -LiteralPath 'C:\Reference\Draft Doc.docx', 'C:\Reference\Images\Diagram [2].vsd' -CompressionLevel Optimal -DestinationPath C:\Archives\Draft.Zip
Comando per creare un nuovo file di archivio Draft.zip
, nella C:\Archives
cartella. Il nuovo file di archivio contiene tutti i file nella cartella C: \ Reference , poiché è stato utilizzato un carattere jolly al posto di nomi di file specifici nel parametro Path .
Compress-Archive -Path C:\Reference\* -CompressionLevel Fastest -DestinationPath C:\Archives\Draft
Il comando crea un archivio da un'intera cartella, C:\Reference
Compress-Archive -Path C:\Reference -DestinationPath C:\Archives\Draft
PowerShell aggiunge automaticamente l' .zip
estensione al nome del file.
Modifica due : questo codice è un brutto, brutto kluge dei tempi antichi. Non lo vuoi.
Questo comprime il contenuto di .\in
to .\out.zip
con System.IO.Packaging.ZipPackage seguendo l'esempio qui
$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()
Modifica: non affidabile per file più grandi, forse> 10mb, YMMV. Qualcosa a che fare con prove di appdomain e archiviazione isolata. L' approccio .NET 4.5 più amichevole funziona bene da PS v3, ma nel mio caso voleva più memoria. Per utilizzare .NET 4 da PS v2, i file di configurazione richiedono una modifica non supportata .
Dare sotto un'altra opzione. Questo comprimerà una cartella intera e scriverà l'archivio in un determinato percorso con il nome dato.
Richiede .NET 3 o versioni successive
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)
Ecco una soluzione nativa per PowerShell v5, utilizzando il cmdlet Compress-Archive
Creazione di file Zip tramite PowerShell .
Vedi anche Microsoft Docs per Compress-Archive .
Esempio 1:
Compress-Archive `
-LiteralPath C:\Reference\Draftdoc.docx, C:\Reference\Images\diagram2.vsd `
-CompressionLevel Optimal `
-DestinationPath C:\Archives\Draft.Zip
Esempio 2:
Compress-Archive `
-Path C:\Reference\* `
-CompressionLevel Fastest `
-DestinationPath C:\Archives\Draft
Esempio 3:
Write-Output $files | Compress-Archive -DestinationPath $outzipfile
Per la compressione, userei una libreria (7-Zip è buono come suggerisce Michal ).
Se installi 7-Zip , la directory installata conterrà 7z.exe
quale è un'applicazione console.
Puoi invocarlo direttamente e utilizzare qualsiasi opzione di compressione desiderata.
Se si desidera interagire con la DLL, anche questo dovrebbe essere possibile.
7-Zip è freeware e open source.
Che dire System.IO.Packaging.ZipPackage
?
Richiederebbe .NET 3.0 o versioni successive.
#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()
via Anders Hesselbom
Perché nessuno guarda la documentazione ?? Esiste un metodo supportato per la creazione di un file zip vuoto e l'aggiunta di singoli file incorporati nella stessa libreria .NET 4.5 a cui tutti fanno riferimento.
Vedi sotto per un esempio di codice:
# 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()
Vi incoraggio a sfogliare la documentazione se avete qualsiasi domanda.
Questo è davvero oscuro ma funziona. 7za.exe è la versione standalone di 7zip ed è disponibile con il pacchetto di installazione.
# 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
}
Se qualcuno deve comprimere un singolo file (e non una cartella): 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
Ecco il codice di lavoro, comprimere tutti i file da una cartella di origine e creare un file zip nella cartella di destinazione.
$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)
}
Nota:
ZipName: percorso completo del file zip che si desidera creare.
SourceDirectory: percorso completo della directory contenente i file che si desidera comprimere.
Ecco una versione leggermente migliorata della risposta di Sonjz, che aggiunge un'opzione di sovrascrittura.
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)
}
Questo dovrebbe funzionare anche per comprimere un singolo file senza usare una cartella temporanea e usare .Net 4.5 nativo, convertito da C # da questa risposta StackOverflow . Usa una sintassi usando più piacevole presa da qui .
Uso:
ZipFiles -zipFilename output.zip -sourceFile input.sql -filename name.inside.zip.sql
Codice:
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)
}
}
}
usando:
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
quell'azienda o 7-Zip / altre utility separate. Mi piace anche la Using-Object
funzione, anche se ho optato per un approccio più breve e veloce senza quello.
Uso questo frammento per controllare la cartella dei backup del mio database per i file di backup non ancora compressi, comprimerli utilizzando 7-Zip e infine eliminare i *.bak
file per risparmiare spazio su disco. Si noti che i file sono ordinati per lunghezza (dal più piccolo al più grande) prima della compressione per evitare che alcuni file non vengano compressi.
$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 }
Qui è possibile controllare uno script di PowerShell per eseguire il backup, comprimere e trasferire quei file su FTP .
Nel caso in cui WinRAR sia installato:
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;
}
Il significato degli argomenti: afzip crea un archivio zip, df elimina i file, ep1 non crea il percorso completo della directory all'interno dell'archivio
Ecco un esempio completo della riga di comando per avviare da cmd.exe o da ssh o quello che vuoi!
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');}"
Saluti
Caricamento del file [System.IO.IOException]
classe e usare i suoi metodi è un passo importante per sopprimere gli errori indesiderati, poiché si tratta di una classe non nativa di PowerShell, quindi aspettati vari contesti di errori senza di essa.
Ho controllato in modo errato il mio script su T, ma ho ottenuto un sacco di output "file esiste" in rosso durante l'utilizzo della [System.IO.Compression.ZipFile]
classe
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
}
}
Quello che sto facendo qui è catturare questi errori IO, come accedere ai file già esistenti, catturare quell'errore e indirizzarlo a un file di registro che sto mantenendo con un programma più grande.
I comandi completi della riga di comando in Windows per la compressione e l'estrazione della directory sono i seguenti:
Per compressione:
powershell.exe -nologo -noprofile -command "& { Add-Type -A 'System.IO.Compression.FileSystem'; [IO.Compression.ZipFile]::CreateFromDirectory('C:\Indus','C:\Indus.zip'); }"
Per estrarre:
powershell.exe -nologo -noprofile -command "& { Add-Type -A 'System.IO.Compression.FileSystem';[IO.Compression.ZipFile]::ExtractToDirectory('C:\Indus.zip','C:\Indus'); }"
L'approccio ionico oscilla:
https://dotnetzip.codeplex.com/wikipage?title=PS-Examples
supporta password, altri metodi crittografici, ecc.
Questo script scorre tutte le directory e comprime ognuna
Get-ChildItem -Attributes d | foreach {write-zip $ .Name "$ ($ .Name) .zip"}