É possível criar um arquivo zip usando o PowerShell?
É possível criar um arquivo zip usando o PowerShell?
Respostas:
Se você seguir para o CodePlex e pegar as Extensões da comunidade do PowerShell , poderá usar o write-zip
cmdlet.
Desde a
O CodePlex está no modo somente leitura, em preparação para o desligamento
você pode acessar a Galeria do PowerShell .
write-zip [input file/folder] [output file]
Uma alternativa pura do PowerShell que funciona com o PowerShell 3 e o .NET 4.5 (se você pode usá-lo):
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 passar o caminho completo para o arquivo zip que você deseja criar e o caminho completo para o diretório que contém os arquivos que você deseja compactar.
Adiciona Compress-Archive
e Expand-Archive
cmdlets do PowerShell v5.0 . As páginas vinculadas têm exemplos completos, mas a essência é:
# 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
Descrição: "... o tamanho máximo do arquivo que você pode compactar usando o Compress-Archive atualmente é de 2 GB. Isso é uma limitação da API subjacente" No entanto, se você usar, System.IO.Compression.ZipFile
poderá ignorar essa limitação.
System.IO.Compression.ZipFile
. Se a estrutura .NET que você está usando não tiver esse limite, o CmdLet não deve atingir esse limite. Eu verifiquei no código.
-OutputPath
parâmetro.
Uma maneira nativa com a estrutura .NET 4.5 mais recente, mas totalmente sem recursos:
Criação:
Add-Type -Assembly "System.IO.Compression.FileSystem" ;
[System.IO.Compression.ZipFile]::CreateFromDirectory("c:\your\directory\to\compress", "yourfile.zip") ;
Extração:
Add-Type -Assembly "System.IO.Compression.FileSystem" ;
[System.IO.Compression.ZipFile]::ExtractToDirectory("yourfile.zip", "c:\your\destination") ;
Como mencionado, totalmente sem recursos, não espere um sinalizador de substituição .
ATUALIZAÇÃO: Veja abaixo outros desenvolvedores que expandiram isso ao longo dos anos ...
Instale o 7zip (ou faça o download da versão da linha de comando) e use este método do 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;
}
Você pode chamar assim:
create-7zip "c:\temp\myFolder" "c:\temp\myFolder.zip"
& "C:\Program Files\7-Zip\7z.exe" a -tzip ($file.FullName+".zip") $file.FullName
O lote mudou desde que a resposta inicial foi lançada. Aqui estão alguns dos exemplos mais recentes usando o comando Compress-Archive .
Comando para criar um novo arquivo compactado, Draft.zip
compactando dois arquivos Draftdoc.docx
e diagram2.vsd
especificado pelo Path
parâmetro O nível de compactação especificado para esta operação é Ótimo.
Compress-Archive -Path C:\Reference\Draftdoc.docx, C:\Reference\Images\diagram2.vsd -CompressionLevel Optimal -DestinationPath C:\Archives\Draft.Zip
Comando para criar um novo arquivo compactado, Draft.zip
compactando dois arquivos Draft doc.docx
e Diagram [2].vsd
especificado pelo LiteralPath
parâmetro O nível de compactação especificado para esta operação é Ótimo.
Compress-Archive -LiteralPath 'C:\Reference\Draft Doc.docx', 'C:\Reference\Images\Diagram [2].vsd' -CompressionLevel Optimal -DestinationPath C:\Archives\Draft.Zip
Comando para criar um novo arquivo morto,, Draft.zip
na C:\Archives
pasta O novo arquivo contém todos os arquivos na pasta C: \ Reference , porque um caractere curinga foi usado no lugar de nomes de arquivo específicos no parâmetro Path .
Compress-Archive -Path C:\Reference\* -CompressionLevel Fastest -DestinationPath C:\Archives\Draft
O comando cria um arquivo morto a partir de uma pasta inteira, C:\Reference
Compress-Archive -Path C:\Reference -DestinationPath C:\Archives\Draft
O PowerShell anexa a .zip
extensão ao nome do arquivo automaticamente.
Editar dois - Este código é um kluge feio e feio dos tempos antigos. Você não quer isso.
Isso comprime o conteúdo de .\in
para .\out.zip
com System.IO.Packaging.ZipPackage, seguindo o exemplo aqui
$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()
Editar: não confiável para arquivos maiores, talvez> 10mb, YMMV. Algo a ver com evidências de domínio de aplicativo e armazenamento isolado. A abordagem mais amigável do .NET 4.5 funciona bem no PS v3, mas queria mais memória no meu caso. Para usar o .NET 4 do PS v2, os arquivos de configuração precisam de um ajuste não suportado .
Dando abaixo outra opção. Isso compactará uma pasta completa e gravará o arquivo morto em um determinado caminho com o nome fornecido.
Requer .NET 3 ou superior
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)
Aqui está uma solução nativa para o PowerShell v5, usando o cmdlet Compress-Archive
Criando arquivos Zip usando o PowerShell .
Consulte também o Microsoft Docs for Compact-Archive .
Exemplo 1:
Compress-Archive `
-LiteralPath C:\Reference\Draftdoc.docx, C:\Reference\Images\diagram2.vsd `
-CompressionLevel Optimal `
-DestinationPath C:\Archives\Draft.Zip
Exemplo 2:
Compress-Archive `
-Path C:\Reference\* `
-CompressionLevel Fastest `
-DestinationPath C:\Archives\Draft
Exemplo 3:
Write-Output $files | Compress-Archive -DestinationPath $outzipfile
Para compactação, eu usaria uma biblioteca (7-Zip é bom como Michal sugere ).
Se você instalar o 7-Zip , o diretório instalado conterá 7z.exe
um aplicativo de console.
Você pode invocá-lo diretamente e usar qualquer opção de compactação que desejar.
Se você deseja se envolver com a DLL, isso também deve ser possível.
7-Zip é freeware e código aberto.
Que tal System.IO.Packaging.ZipPackage
?
Seria necessário o .NET 3.0 ou superior.
#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
Por que ninguém olha a documentação? Existe um método suportado de criar um arquivo zip vazio e adicionar arquivos individuais a ele embutidos na mesma biblioteca do .NET 4.5 que todo mundo está fazendo referência.
Veja abaixo um exemplo de código:
# 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()
Convido você a procurar a documentação se tiver alguma dúvida.
Isso é realmente obscuro, mas funciona. 7za.exe é a versão autônoma do 7zip e está disponível no pacote de instalação.
# 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 alguém precisar compactar um único arquivo (e não uma pasta): 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
Aqui está o código de trabalho, compactando todos os arquivos de uma pasta de origem e crie um arquivo zip na pasta de destino.
$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: caminho completo do arquivo zip que você deseja criar.
SourceDirectory: Caminho completo para o diretório que contém os arquivos que você deseja compactar.
Aqui está uma versão ligeiramente melhorada da resposta do sonjz, que adiciona uma opção de substituição.
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)
}
Isso também deve funcionar para compactar um único arquivo sem usar uma pasta temporária e usar o .Net 4.5 nativo, convertido de C # a partir desta resposta do StackOverflow . Ele usa uma sintaxe mais agradável usando aqui .
Uso:
ZipFiles -zipFilename output.zip -sourceFile input.sql -filename name.inside.zip.sql
Código:
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
negócio ou 7-Zip / outros utilitários separados. Também gosto da Using-Object
função, apesar de ter adotado uma abordagem mais rápida e rápida sem sujeira.
Eu uso esse trecho para verificar a pasta de backups do meu banco de dados em busca de arquivos de backup ainda não compactados, compactá-los usando o 7-Zip e finalmente excluir os *.bak
arquivos para economizar espaço em disco. Os arquivos de aviso são ordenados por tamanho (do menor para o maior) antes da compactação para evitar que alguns arquivos não sejam compactados.
$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 }
Aqui você pode verificar um script do PowerShell para fazer backup, compactar e transferir esses arquivos por FTP .
Caso você tenha o WinRAR instalado:
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;
}
O significado dos argumentos: afzip cria arquivo zip, df exclui arquivos, ep1 não cria o caminho completo do diretório dentro do arquivo
Aqui está um exemplo completo da linha de comando para iniciar a partir do cmd.exe ou do ssh ou o que você quiser!
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');}"
Saudações
Carregar a [System.IO.IOException]
classe e usar seus métodos é uma etapa importante para suprimir erros indesejados, devido ao fato de ser uma classe não nativa do PowerShell, portanto, espere vários contextos de erros sem ela.
Eu controlei meu script com erro no T, mas obtive um monte de saída extra de 'arquivo vermelho' ao usar a [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
}
}
O que estou fazendo aqui é capturar esses erros de E / S, como acessar arquivos que já existem, capturar esse erro e direcioná-lo para um arquivo de log que estou mantendo com um programa maior.
Os comandos completos da linha de comando no Windows para compactar e extrair o diretório são os seguintes:
Para compressão:
powershell.exe -nologo -noprofile -command "& { Add-Type -A 'System.IO.Compression.FileSystem'; [IO.Compression.ZipFile]::CreateFromDirectory('C:\Indus','C:\Indus.zip'); }"
Para extrair:
powershell.exe -nologo -noprofile -command "& { Add-Type -A 'System.IO.Compression.FileSystem';[IO.Compression.ZipFile]::ExtractToDirectory('C:\Indus.zip','C:\Indus'); }"
A abordagem iônica é fundamental:
https://dotnetzip.codeplex.com/wikipage?title=PS-Examples
suporta senhas, outros métodos de criptografia, etc.