Come decomprimere un file in Powershell?


224

Ho un .zipfile e devo decomprimere il suo intero contenuto usando Powershell. Lo sto facendo ma non sembra funzionare:

$shell = New-Object -ComObject shell.application
$zip = $shell.NameSpace("C:\a.zip")
MkDir("C:\a")
foreach ($item in $zip.items()) {
  $shell.Namespace("C:\a").CopyHere($item)
}

Cosa c'è che non va? La directory C:\aè ancora vuota.


6
Se sei in Powershell 2.0 o senza .NET 4.5 installato, il metodo che hai citato è l'unico percorso (senza andare con un exe di terze parti (ad esempio 7zip). Direi che alla domanda non viene data una risposta completa fino a quando qualcuno spiega perché questo metodo non funziona. Lo fa per me alcune volte, ma altri no.
kenny

Risposte:


248

Ecco un modo semplice utilizzando ExtractToDirectory da System.IO.Compression.ZipFile :

Add-Type -AssemblyName System.IO.Compression.FileSystem
function Unzip
{
    param([string]$zipfile, [string]$outpath)

    [System.IO.Compression.ZipFile]::ExtractToDirectory($zipfile, $outpath)
}

Unzip "C:\a.zip" "C:\a"

Si noti che se la cartella di destinazione non esiste, ExtractToDirectory la creerà. Altre avvertenze:

Guarda anche:


10
Perché si crea una funzione per sostituire una singola chiamata di funzione?

17
In teoria no. Cerco di nascondere chiamate complesse / non convenzionali nelle funzioni, quindi in seguito posso sostituire il metodo senza preoccuparmi di dove viene utilizzato. Come ha detto Keith, in V5 ci sarà un nuovo modo di farlo.
Micky Balladelli,

1
Per questo è necessario almeno .NET Framework 4.5. Vedere la parte inferiore della msdn.microsoft.com/en-us/library/...
ferventcoder

10
Ho provato questo, ma ottenendo un errore inferiore, Exception calling "ExtractToDirectory" with "2" argument(s): "End of Central Directory record could not be found." At line:5 char:5 + [System.IO.Compression.ZipFile]::ExtractToDirectory($zipfile, $ou ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], MethodInvocationException + FullyQualifiedErrorId : InvalidDataException
Karthi1234,

4
Questo mi dà l'errore seguente: Add-Type : Cannot add type. The assembly 'System.IO.Compression.FileSystem' could not be found.. Ho installato .NET 4.6.2 e ho verificato che l'assembly si trova nel GAC, ma non ho capito perché sto ricevendo questo errore.
Sam,

500

In PowerShell v5 + è presente un comando Expand-Archive (oltre a Compress-Archive) incorporato:

Expand-Archive c:\a.zip -DestinationPath c:\a

26
Utilizzare $PSVersionTable.PSVersionper determinare quale versione di PowerShell è in esecuzione.
Brad C

1
@LoneCoder Non credo che tu possa incolpare Ballmer. Windows non ha mai avuto uno strumento da riga di comando integrato per gestire i file compressi prima, anche se gzip è uscito nel 1992 e tar è ancora più vecchio.
jpmc26

2
@Ghashange PowerShell 5 non era nemmeno disponibile per nulla al di sotto di Windows 10 e Server 2012 quando questa risposta è stata pubblicata, anche come pre-release.
jpmc26

11
Sembra che il parametro OutputPathsia stato modificato in DestinationPath(riferimento msdn.microsoft.com/powershell/reference/5.1/… )
Elija W. Gagne

1
Puoi anche usare percorsi relativi comeExpand-Archive -Path .\a.zip -DestinationPath .
Culip

24

In PowerShell v5.1 questo è leggermente diverso rispetto alla v5. Secondo la documentazione MS, deve disporre di un -Pathparametro per specificare il percorso del file di archivio.

Expand-Archive -Path Draft.Zip -DestinationPath C:\Reference

Altrimenti, questo può essere un percorso effettivo:

Expand-Archive -Path c:\Download\Draft.Zip -DestinationPath C:\Reference

Expand-Archive Doc


3
Non vi è alcuna differenza tra v5 e v5.1 in questo cmdlet. Non è necessario nominare il primo parametro; diventerà automaticamente il percorso. Ad esempio, Expand-Archive Draft.Zip -DestinationPath C:\Referencefunziona senza problemi. Inoltre, non è il percorso effettivo , ma il percorso assoluto .
Franklin Yu,

13

Utilizzare il Expand-Archivecmdlet con uno dei set di parametri:

Expand-Archive -LiteralPath C:\source\file.Zip -DestinationPath C:\destination
Expand-Archive -Path file.Zip -DestinationPath C:\destination

12

Ehi, sta funzionando per me ..

$shell = New-Object -ComObject shell.application
$zip = $shell.NameSpace("put ur zip file path here")
foreach ($item in $zip.items()) {
  $shell.Namespace("destination where files need to unzip").CopyHere($item)
}

2
Se uno dei file o delle directory esiste già nella posizione di destinazione, si apre un dialogo che chiede cosa fare (ignorare, sovrascrivere) che vanifica lo scopo. Qualcuno sa come forzarlo a sovrascrivere silenziosamente?
Oleg Kazakov,

Risposta al commento di @OlegKazakov: esiste una serie di opzioni che controllano il CopyHeremetodo. Immagino che @OlegKazakov abbia già risolto il suo problema. Tuttavia ho inserito questo link qui per altri navigatori che possono trovare questo argomento: docs.microsoft.com/en-us/previous-versions/windows/desktop/…
jsxt

4

Per coloro che desiderano utilizzare Shell.Application.Namespace.Folder.CopyHere () e vogliono nascondere le barre di avanzamento durante la copia o utilizzare più opzioni, la documentazione è qui:
https://docs.microsoft.com/en-us / windows / desktop / shell / cartella-CopyHere

Per utilizzare PowerShell e nascondere le barre di avanzamento e disabilitare le conferme, è possibile utilizzare il codice in questo modo:

# We should create folder before using it for shell operations as it is required
New-Item -ItemType directory -Path "C:\destinationDir" -Force

$shell = New-Object -ComObject Shell.Application
$zip = $shell.Namespace("C:\archive.zip")
$items = $zip.items()
$shell.Namespace("C:\destinationDir").CopyHere($items, 1556)

Limitazioni d'uso di Shell.Application su versioni core di Windows:
https://docs.microsoft.com/en-us/windows-server/administration/server-core/what-is-server-core

Sulle versioni core di Windows , per impostazione predefinita il pacchetto Microsoft-Windows-Server-Shell-Package non è installato, quindi shell.applicaton non funzionerà.

nota : l'estrazione di archivi in ​​questo modo richiederà molto tempo e può rallentare l'interfaccia grafica di Windows


3

Utilizzo expand-archivema creazione automatica di directory che prendono il nome dall'archivio:

function unzip ($file) {
    $dirname = (Get-Item $file).Basename
    New-Item -Force -ItemType directory -Path $dirname
    expand-archive $file -OutputPath $dirname -ShowProgress
}

Questo si espande necessariamente nella directory corrente, no?
jpmc26

Non vedo davvero il valore aggiunto della creazione automatica. È più flessibile aggiungere un secondo parametro outputPathcome nella risposta accettata. In questa soluzione (come diceva jpmc26), creerai sempre una nuova directory nella directory corrente, quindi è possibile che tu debba impostare la directory corrente prima di chiamareunzip
Rubanov,

La maggior parte degli archivi estrae in una directory che prende il nome dall'archivio, nello stesso posto dell'archivio. Nulla ti impedisce di aggiungere parametri se vuoi qualcosa di diverso, ma è un valore predefinito ragionevole.
mikemaccana,

1
function unzip {
    param (
        [string]$archiveFilePath,
        [string]$destinationPath
    )

    if ($archiveFilePath -notlike '?:\*') {
        $archiveFilePath = [System.IO.Path]::Combine($PWD, $archiveFilePath)
    }

    if ($destinationPath -notlike '?:\*') {
        $destinationPath = [System.IO.Path]::Combine($PWD, $destinationPath)
    }

    Add-Type -AssemblyName System.IO.Compression
    Add-Type -AssemblyName System.IO.Compression.FileSystem

    $archiveFile = [System.IO.File]::Open($archiveFilePath, [System.IO.FileMode]::Open)
    $archive = [System.IO.Compression.ZipArchive]::new($archiveFile)

    if (Test-Path $destinationPath) {
        foreach ($item in $archive.Entries) {
            $destinationItemPath = [System.IO.Path]::Combine($destinationPath, $item.FullName)

            if ($destinationItemPath -like '*/') {
                New-Item $destinationItemPath -Force -ItemType Directory > $null
            } else {
                New-Item $destinationItemPath -Force -ItemType File > $null

                [System.IO.Compression.ZipFileExtensions]::ExtractToFile($item, $destinationItemPath, $true)
            }
        }
    } else {
        [System.IO.Compression.ZipFileExtensions]::ExtractToDirectory($archive, $destinationPath)
    }
}

usando:

unzip 'Applications\Site.zip' 'C:\inetpub\wwwroot\Site'

Non dimenticare di smaltire $archivee $archiveFilealla fine
tom.maruska il

0

ForEachIl ciclo elabora ogni file ZIP situato all'interno della $filepathvariabile

    foreach($file in $filepath)
    {
        $zip = $shell.NameSpace($file.FullName)
        foreach($item in $zip.items())
        {
            $shell.Namespace($file.DirectoryName).copyhere($item)
        }
        Remove-Item $file.FullName
    }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.