PowerShell, Zip & Unzip

OpenBazaar
OpenBazaar, Aperto al business
5 aprile 2016
Let's Encrypt
Attivare facilmente e gratuitamente HTTPS (non self-signed!)
13 aprile 2016
Mostra tutto

PowerShell, Zip & Unzip

PowerShell Zip
Spesso e volentieri lavorando in PowerShell si ha la necessità di creare degli archivi compressi, purtroppo fino all'arrivo di Windows 10 (ovvero di PowerShell 5.0) e dei cmdlet Compress-Archive e Expand-Archive l'oprazione non è così semplice e intuitiva come invece si pensa. Vediamo quindi come procedere.

PowerShell 5.0

Per creare un archivio compresso utilizzare:
Compress-Archive C:\Sorgente C:\Destinazione\Files.zip -Force -Verbose
Per estrarre un archivio compresso utilizzare:
Expand-Archive C:\Sorgente\Files.zip -DestinationPath C:\Destinazione\ -Force -Verbose

PowerShell 3.0 e 4.0

Funzione di Compressione:
    Add-Type -As System.IO.Compression.FileSystem
     
    function New-ZipFile {
      #.Synopsis
      #  Create a new zip file, optionally appending to an existing zip...
      [CmdletBinding()]
      param(
        # The path of the zip to create
        [Parameter(Position=0, Mandatory=$true)]
        $ZipFilePath,
     
        # Items that we want to add to the ZipFile
        [Parameter(Position=1, Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
        [Alias("PSPath","Item")]
        [string[]]$InputObject = $Pwd,
     
        # Append to an existing zip file, instead of overwriting it
        [Switch]$Append,
     
        # The compression level (defaults to Optimal):
        #   Optimal - The compression operation should be optimally compressed, even if the operation takes a longer time to complete.
        #   Fastest - The compression operation should complete as quickly as possible, even if the resulting file is not optimally compressed.
        #   NoCompression - No compression should be performed on the file.
        [System.IO.Compression.CompressionLevel]$Compression = "Optimal"
      )
      begin {
        # Make sure the folder already exists
        [string]$File = Split-Path $ZipFilePath -Leaf
        [string]$Folder = $(if($Folder = Split-Path $ZipFilePath) { Resolve-Path $Folder } else { $Pwd })
        $ZipFilePath = Join-Path $Folder $File
        # If they don't want to append, make sure the zip file doesn't already exist.
        if(!$Append) {
          if(Test-Path $ZipFilePath) { Remove-Item $ZipFilePath }
        }
        $Archive = [System.IO.Compression.ZipFile]::Open( $ZipFilePath, "Update" )
      }
      process {
        foreach($path in $InputObject) {
          foreach($item in Resolve-Path $path) {
            # Push-Location so we can use Resolve-Path -Relative
            Push-Location (Split-Path $item)
            # This will get the file, or all the files in the folder (recursively)
            foreach($file in Get-ChildItem $item -Recurse -File -Force | % FullName) {
              # Calculate the relative file path
              $relative = (Resolve-Path $file -Relative).TrimStart(".\")
              # Add the file to the zip
              $null = [System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($Archive, $file, $relative, $Compression)
            }
            Pop-Location
          }
        }
      }
      end {
        $Archive.Dispose()
        Get-Item $ZipFilePath
      }
    }
Funzione di Decompressione:
function Expand-ZipFile {
      #.Synopsis
      #  Expand a zip file, ensuring it's contents go to a single folder ...
      [CmdletBinding()]
      param(
        # The path of the zip file that needs to be extracted
        [Parameter(ValueFromPipelineByPropertyName=$true, Position=0, Mandatory=$true)]
        [Alias("PSPath")]
        $FilePath,
     
        # The path where we want the output folder to end up
        [Parameter(Position=1)]
        $OutputPath = $Pwd,
     
        # Make sure the resulting folder is always named the same as the archive
        [Switch]$Force
      )
      process {
        $ZipFile = Get-Item $FilePath
        $Archive = [System.IO.Compression.ZipFile]::Open( $ZipFile, "Read" )
     
        # Figure out where we'd prefer to end up
        if(Test-Path $OutputPath) {
          # If they pass a path that exists, we want to create a new folder
          $Destination = Join-Path $OutputPath $ZipFile.BaseName
        } else {
          # Otherwise, since they passed a folder, they must want us to use it
          $Destination = $OutputPath
        }
     
        # The root folder of the first entry ...
        $ArchiveRoot = ($Archive.Entries[0].FullName -Split "/|\\")[0]
     
        Write-Verbose "Desired Destination: $Destination"
        Write-Verbose "Archive Root: $ArchiveRoot"
     
        # If any of the files are not in the same root folder ...
        if($Archive.Entries.FullName | Where-Object { @($_ -Split "/|\\")[0] -ne $ArchiveRoot }) {
          # extract it into a new folder:
          New-Item $Destination -Type Directory -Force
          [System.IO.Compression.ZipFileExtensions]::ExtractToDirectory( $Archive, $Destination )
        } else {
          # otherwise, extract it to the OutputPath
          [System.IO.Compression.ZipFileExtensions]::ExtractToDirectory( $Archive, $OutputPath )
     
          # If there was only a single file in the archive, then we'll just output that file...
          if($Archive.Entries.Count -eq 1) {
            # Except, if they asked for an OutputPath with an extension on it, we'll rename the file to that ...
            if([System.IO.Path]::GetExtension($Destination)) {
              Move-Item (Join-Path $OutputPath $Archive.Entries[0].FullName) $Destination
            } else {
              Get-Item (Join-Path $OutputPath $Archive.Entries[0].FullName)
            }
          } elseif($Force) {
            # Otherwise let's make sure that we move it to where we expect it to go, in case the zip's been renamed
            if($ArchiveRoot -ne $ZipFile.BaseName) {
              Move-Item (join-path $OutputPath $ArchiveRoot) $Destination
              Get-Item $Destination
            }
          } else {
            Get-Item (Join-Path $OutputPath $ArchiveRoot)
          }
        }
     
        $Archive.Dispose()
      }
    }

Alternativa con 7-Zip (o WinRar)

Un'altra alternativa è quella di installare 7-Zip o WinRar (o il solo binario se non si vuole una full-install) e di passargli i files come li si passerebbe da un DOS Prompt standard.

3 Comments

  1. https://Www.linkedin.com/ scrive:

    Excellent post. I was checking constantly this blog and
    I’m inspired! Very useful information specifically tthe final phase 🙂 I handle such info much.
    I used tto be seeking this certain informatipn for a long time.
    Thank you and best of luck.

  2. Victoria scrive:

    This is a topic that’s near to my heart… Cheers! Exactly where are your contact details though?

  3. Holistic Health scrive:

    Great post! We are linking to this great content on our website. Keep up the great writing.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *