Как создать zip-архив с помощью PowerShell?




12 Answers

Чистая альтернатива PowerShell, которая работает с 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)
}

Просто перейдите в полный путь к zip-архиву, который вы хотите создать, и полный путь к каталогу, содержащему файлы, которые вы хотели бы заархивировать.

powershell zip

Можно ли создать zip-архив с помощью PowerShell?




Родной способ с последней платформой .NET 4.5, но полностью не имеющий значения:

Создание:

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") ;

Как уже упоминалось, полностью бескомпромиссны, поэтому не ожидайте флаг перезаписи .

ОБНОВЛЕНИЕ: см. Ниже для других разработчиков, которые расширялись на протяжении многих лет ...




Изменить два - этот код является уродливым, уродливым kluge из старых дней. Ты не хочешь этого.

Это сжимает содержимое .\out.zip to .\out.zip с помощью System.IO.Packaging.ZipPackage, следующего за примером here

$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()

Изменить: Unreliable для больших файлов, возможно> 10mb, YMMV. Something связано с доказательством апдомена и изолированным хранилищем. Дружелюбный approach .NET 4.5 отлично работает с PS v3, но в моем случае требуется больше памяти. Чтобы использовать .NET 4 из PS v2, для конфигурационных файлов требуется unsupported tweak .




Для сжатия я бы использовал библиотеку (7-Zip хорош, как предлагает Michal ).

Если вы устанавливаете 7-Zip , установленный каталог будет содержать 7z.exe который является консольным приложением.
Вы можете вызвать его напрямую и использовать любой параметр сжатия, который вы хотите.

Если вы хотите взаимодействовать с DLL, это также должно быть возможно.
7-Zip - бесплатная и открытая программа.




Это действительно неясно, но работает. 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



Вот рабочий код, zipping всех файлов из исходной папки и создание zip-файла в папке назначения.

    $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.."



Вот полный пример командной строки для запуска из 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');}"

С уважением




Я использую этот фрагмент, чтобы проверить папку резервных копий базы данных для файлов резервных копий, которые еще не сжаты, сжимать их с помощью 7-Zip и, наконец, удалять файлы *.bak для сохранения некоторого дискового пространства. Файлы уведомлений упорядочиваются по длине (от самого маленького к большому) до сжатия, чтобы избежать сжатия некоторых файлов.

$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 .




Загрузка класса [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 
    }
} 

То, что я делаю здесь, - это перехват этих ошибок ввода-вывода, таких как доступ к уже существующим файлам, обнаружение этой ошибки и направление ее в файл журнала, который я поддерживаю с помощью более крупной программы.




Этот скрипт выполняет итерацию всех каталогов и zip каждый

Get-ChildItem -Attributes d | foreach {write-zip $ .Name "$ ($ .Name) .zip"}




Related