¿Es posible crear un archivo zip usando PowerShell?
¿Es posible crear un archivo zip usando PowerShell?
Respuestas:
Si te diriges a CodePlex y tomas las Extensiones de comunidad de PowerShell , puedes usar su write-zip
cmdlet.
Ya que
CodePlex está en modo de solo lectura en preparación para el apagado
puedes ir a la galería de PowerShell .
write-zip [input file/folder] [output file]
Una alternativa pura de PowerShell que funciona con PowerShell 3 y .NET 4.5 (si puede 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)
}
Simplemente pase la ruta completa al archivo zip que desea crear y la ruta completa al directorio que contiene los archivos que desea comprimir.
PowerShell v5.0 agrega Compress-Archive
y Expand-Archive
cmdlets. Las páginas vinculadas tienen ejemplos completos, pero lo esencial es:
# 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
Descripción: "... el tamaño máximo de archivo que puede comprimir usando Compress-Archive es actualmente de 2 GB. Esto es una limitación de la API subyacente" Sin embargo, si lo usa System.IO.Compression.ZipFile
, puede omitir esta limitación.
System.IO.Compression.ZipFile
. Si el marco .NET que está utilizando no tiene este límite, CmdLet no debería alcanzar este límite. Lo verifiqué en el código.
-OutputPath
parámetro.
Una forma nativa con el último framework .NET 4.5, pero completamente sin características:
Creación:
Add-Type -Assembly "System.IO.Compression.FileSystem" ;
[System.IO.Compression.ZipFile]::CreateFromDirectory("c:\your\directory\to\compress", "yourfile.zip") ;
Extracción:
Add-Type -Assembly "System.IO.Compression.FileSystem" ;
[System.IO.Compression.ZipFile]::ExtractToDirectory("yourfile.zip", "c:\your\destination") ;
Como se mencionó, totalmente sin características, así que no esperes una marca de sobrescritura .
ACTUALIZACIÓN: Vea a continuación otros desarrolladores que se han expandido en esto a lo largo de los años ...
Instale 7zip (o descargue la versión de línea de comando en su lugar) y use este método de 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;
}
Puedes llamarlo así:
create-7zip "c:\temp\myFolder" "c:\temp\myFolder.zip"
& "C:\Program Files\7-Zip\7z.exe" a -tzip ($file.FullName+".zip") $file.FullName
El lote ha cambiado desde que se publicó la respuesta inicial. Estos son algunos de los últimos ejemplos que utilizan el comando Compress-Archive .
Comando para crear un nuevo archivo Draft.zip
comprimido comprimiendo dos archivos Draftdoc.docx
y diagram2.vsd
especificado por el Path
parámetro. El nivel de compresión especificado para esta operación es Óptimo.
Compress-Archive -Path C:\Reference\Draftdoc.docx, C:\Reference\Images\diagram2.vsd -CompressionLevel Optimal -DestinationPath C:\Archives\Draft.Zip
Comando para crear un nuevo archivo comprimido, Draft.zip
al comprimir dos archivos Draft doc.docx
y Diagram [2].vsd
, especificado por el LiteralPath
parámetro. El nivel de compresión especificado para esta operación es Óptimo.
Compress-Archive -LiteralPath 'C:\Reference\Draft Doc.docx', 'C:\Reference\Images\Diagram [2].vsd' -CompressionLevel Optimal -DestinationPath C:\Archives\Draft.Zip
Comando para crear un nuevo archivo comprimido,, Draft.zip
en la C:\Archives
carpeta. El nuevo archivo contiene todos los archivos de la carpeta C: \ Reference , porque se utilizó un carácter comodín en lugar de nombres de archivo específicos en el parámetro Path .
Compress-Archive -Path C:\Reference\* -CompressionLevel Fastest -DestinationPath C:\Archives\Draft
Command crea un archivo de una carpeta completa, C:\Reference
Compress-Archive -Path C:\Reference -DestinationPath C:\Archives\Draft
PowerShell agrega la .zip
extensión al nombre del archivo automáticamente.
Editar dos : este código es un feo, feo kluge de antaño. No lo quieres.
Esto comprime el contenido de .\in
a .\out.zip
con System.IO.Packaging.ZipPackage siguiendo el ejemplo aquí
$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: No confiable para archivos más grandes, tal vez> 10mb, YMMV. Algo relacionado con la evidencia de dominio de aplicación y el almacenamiento aislado. El enfoque más amigable .NET 4.5 funciona bien desde PS v3, pero quería más memoria en mi caso. Para usar .NET 4 de PS v2, los archivos de configuración necesitan un ajuste no compatible .
Dando a continuación otra opción. Esto comprimirá una carpeta completa y escribirá el archivo en una ruta determinada con el nombre.
Requiere .NET 3 o 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)
Aquí hay una solución nativa para PowerShell v5, usando el cmdlet Compress-Archive
Creación de archivos Zip usando PowerShell .
Consulte también Microsoft Docs para Compress-Archive .
Ejemplo 1:
Compress-Archive `
-LiteralPath C:\Reference\Draftdoc.docx, C:\Reference\Images\diagram2.vsd `
-CompressionLevel Optimal `
-DestinationPath C:\Archives\Draft.Zip
Ejemplo 2
Compress-Archive `
-Path C:\Reference\* `
-CompressionLevel Fastest `
-DestinationPath C:\Archives\Draft
Ejemplo 3
Write-Output $files | Compress-Archive -DestinationPath $outzipfile
Para la compresión, usaría una biblioteca (7-Zip es bueno, como sugiere Michal ).
Si instala 7-Zip , el directorio instalado contendrá 7z.exe
la aplicación de consola.
Puede invocarlo directamente y usar cualquier opción de compresión que desee.
Si desea participar con la DLL, eso también debería ser posible.
7-Zip es un programa gratuito y de código abierto.
¿Qué hay de System.IO.Packaging.ZipPackage
?
Requeriría .NET 3.0 o 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()
a través de Anders Hesselbom
¿Por qué nadie mira la documentación? Hay un método compatible para crear un archivo zip vacío y agregar archivos individuales integrados en la misma biblioteca .NET 4.5 a la que todos hacen referencia.
Vea a continuación un ejemplo 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()
Le recomiendo que explore la documentación si tiene alguna pregunta.
Esto es realmente oscuro pero funciona. 7za.exe es una versión independiente de 7zip y está disponible con el paquete de instalación.
# 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
}
Si alguien necesita comprimir un solo archivo (y no una carpeta): 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
Aquí está el código de trabajo, comprime todos los archivos de una carpeta de origen y crea un archivo zip en la carpeta 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: ruta completa del archivo Zip que desea crear.
SourceDirectory: ruta completa al directorio que contiene los archivos que desea comprimir.
Aquí hay una versión ligeramente mejorada de la respuesta de sonjz, agrega una opción de sobrescritura.
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)
}
Esto también debería funcionar para comprimir un solo archivo sin usar una carpeta temporal y usar .Net 4.5 nativo, convertido de C # a partir de esta respuesta de StackOverflow . Utiliza una mejor sintaxis tomada de aquí .
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)
}
}
}
Utilizando:
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
negocio u 7-Zip / otras utilidades separadas. También me gusta la Using-Object
función, aunque elegí un enfoque más corto, rápido y sucio sin eso.
Utilizo este fragmento para verificar la carpeta de copias de seguridad de mi base de datos para archivos de copia de seguridad aún no comprimidos, comprimirlos usando 7-Zip y finalmente eliminar los *.bak
archivos para ahorrar espacio en el disco. Los archivos de aviso se ordenan por longitud (de menor a mayor) antes de la compresión para evitar que algunos archivos no se compriman.
$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 }
Aquí puede verificar un script de PowerShell para hacer copias de seguridad, comprimir y transferir esos archivos a través de FTP .
En caso de que tenga instalado 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;
}
El significado de los argumentos: afzip crea un archivo zip, df elimina archivos, ep1 no crea la ruta completa del directorio dentro del archivo
¡Aquí hay un ejemplo de línea de comando completo para iniciar desde cmd.exe o desde ssh o lo que quieras!
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');}"
Saludos
Cargar la [System.IO.IOException]
clase y usar sus métodos es un paso importante para suprimir errores no deseados, debido al hecho de que es una clase no nativa de PowerShell, por lo tanto, espere varios contextos de errores sin ella.
Controlé por error mi script a la T, pero obtuve una gran cantidad de salida roja 'archivo existe' mientras usaba la [System.IO.Compression.ZipFile]
clase
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
}
}
Lo que estoy haciendo aquí es detectar estos errores de E / S, como acceder a archivos que ya existen, detectar ese error y dirigirlo a un archivo de registro que estoy manteniendo con un programa más grande.
Los comandos completos de la línea de comandos en Windows para comprimir y extraer directorios son los siguientes:
Para la compresión:
powershell.exe -nologo -noprofile -command "& { Add-Type -A 'System.IO.Compression.FileSystem'; [IO.Compression.ZipFile]::CreateFromDirectory('C:\Indus','C:\Indus.zip'); }"
Para extraer:
powershell.exe -nologo -noprofile -command "& { Add-Type -A 'System.IO.Compression.FileSystem';[IO.Compression.ZipFile]::ExtractToDirectory('C:\Indus.zip','C:\Indus'); }"
El enfoque iónico oscila:
https://dotnetzip.codeplex.com/wikipage?title=PS-Examples
admite contraseñas, otros métodos de cifrado, etc.
Este script itera todos los directorios y comprime cada uno
Get-ChildItem -Attributes d | foreach {write-zip $ .Name "$ ($ .Name) .zip"}