Comment décompresser un fichier dans Powershell?


224

J'ai un .zipfichier et j'ai besoin de décompresser tout son contenu à l'aide de Powershell. Je fais ça mais ça ne semble pas fonctionner:

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

Qu'est-ce qui ne va pas? Le répertoire C:\aest toujours vide.


6
Si vous êtes dans Powershell 2.0, ou sans .NET 4.5 installé, alors la méthode que vous avez mentionnée est le seul chemin (sans aller avec un exe tiers (c'est-à-dire 7zip). Je dirais que la question n'est pas entièrement répondue jusqu'à ce que quelqu'un explique pourquoi cette méthode ne fonctionne pas. Elle le fait pour moi une partie du temps, mais d'autres non.
kenny

Réponses:


248

Voici un moyen simple d'utiliser ExtractToDirectory de 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"

Notez que si le dossier cible n'existe pas, ExtractToDirectory le créera. Autres mises en garde:

Voir également:


10
Pourquoi créez-vous une fonction pour remplacer un seul appel de fonction?

17
En théorie, non. J'essaie de cacher les appels complexes / non conventionnels dans les fonctions afin que plus tard je puisse remplacer la méthode sans se soucier de l'endroit où elle est utilisée. Comme Keith l'a mentionné, dans V5, il y aura une nouvelle façon de le faire.
Micky Balladelli du

1
Pour cela, vous avez besoin d'au moins .NET Framework 4.5. Voir le bas de msdn.microsoft.com/en-us/library/…
ferventcoder

10
J'ai essayé cela, mais en dessous de l'erreur, 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
Cela me donne l'erreur suivante: Add-Type : Cannot add type. The assembly 'System.IO.Compression.FileSystem' could not be found.. J'ai .NET 4.6.2 installé et j'ai vérifié que l'assembly est dans le GAC, mais je n'ai pas compris pourquoi j'obtiens cette erreur.
Sam

500

Dans PowerShell v5 +, il existe une commande Expand-Archive (ainsi que Compress-Archive) intégrée dans:

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

26
Utilisez $PSVersionTable.PSVersionpour déterminer la version de PowerShell que vous exécutez.
Brad C

1
@LoneCoder Je ne pense pas que vous puissiez blâmer Ballmer. Windows n'a jamais eu auparavant d'outil de ligne de commande intégré pour gérer les fichiers compressés, même si gzip est sorti en 1992 et que tar est encore plus ancien.
jpmc26

2
@Ghashange PowerShell 5 n'était même pas disponible pour tout ce qui est inférieur à Windows 10 et Server 2012 lorsque cette réponse a été publiée, même en version préliminaire.
jpmc26

11
On dirait que le paramètre OutputPatha été changé en DestinationPath(référence msdn.microsoft.com/powershell/reference/5.1/… )
Elijah W. Gagne

1
Vous pouvez également utiliser des chemins relatifs commeExpand-Archive -Path .\a.zip -DestinationPath .
Culip

24

Dans PowerShell v5.1, cela est légèrement différent de v5. Selon la documentation MS, il doit avoir un -Pathparamètre pour spécifier le chemin du fichier d'archive.

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

Ou bien, cela peut être un chemin réel:

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

Expand-Archive Doc


3
Il n'y a aucune différence entre la v5 et la v5.1 dans cette applet de commande. Vous n'avez pas besoin de nommer le premier paramètre; il deviendra automatiquement le chemin. Par exemple, Expand-Archive Draft.Zip -DestinationPath C:\Referencefonctionne sans problème. De plus, ce n'est pas un chemin réel , mais un chemin absolu .
Franklin Yu

13

Utilisez l' Expand-Archiveapplet de commande avec l'un des jeux de paramètres:

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

12

Hey ça marche pour moi ..

$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
Si l'un des fichiers ou répertoires existe déjà à l'emplacement de destination, il ouvre une boîte de dialogue vous demandant quoi faire (ignorer, écraser) qui va à l'encontre de l'objectif. Est-ce que quelqu'un sait comment le forcer à écraser silencieusement?
Oleg Kazakov

Réponse au commentaire de @OlegKazakov: il existe un ensemble d'options contrôlant la CopyHereméthode. Je suppose que @OlegKazakov a déjà résolu son problème. Néanmoins, je mets ce lien ici pour les autres surfeurs qui peuvent trouver ce sujet: docs.microsoft.com/en-us/previous-versions/windows/desktop/…
jsxt

4

Pour ceux qui souhaitent utiliser Shell.Application.Namespace.Folder.CopyHere () et veulent masquer les barres de progression lors de la copie, ou utiliser plus d'options, la documentation est ici:
https://docs.microsoft.com/en-us / windows / desktop / shell / folder-copyhere

Pour utiliser PowerShell et masquer les barres de progression et désactiver les confirmations, vous pouvez utiliser un code comme celui-ci:

# 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)

Limitations d'utilisation de Shell.Application sur les versions de base de Windows:
https://docs.microsoft.com/en-us/windows-server/administration/server-core/what-is-server-core

Sur les versions de base de Windows , par défaut, Microsoft-Windows-Server-Shell-Package n'est pas installé, donc shell.applicaton ne fonctionnera pas.

Remarque : l'extraction des archives de cette manière prendra beaucoup de temps et peut ralentir l'interface graphique de Windows.


3

Utilisation expand-archivemais création automatique de répertoires nommés d'après l'archive:

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

Cela se développe nécessairement dans le répertoire courant, n'est-ce pas?
jpmc26

Ne voyez pas vraiment la valeur ajoutée de la création automatique. Il est plus flexible d'ajouter un deuxième paramètre outputPathcomme dans la réponse acceptée. Dans cette solution (comme l'a dit jpmc26), vous créerez toujours un nouveau répertoire dans le répertoire actuel, il est donc possible que vous deviez définir le répertoire actuel avant d'appelerunzip
Rubanov

La plupart des archiveurs extraient dans un répertoire nommé d'après l'archive, au même endroit que l'archive. Rien ne vous empêche d'ajouter des paramètres si vous voulez quelque chose de différent, mais c'est un défaut raisonnable.
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)
    }
}

En utilisant:

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

N'oubliez pas de disposer $archiveet $archiveFileà la fin
tom.maruska

0

ForEachLa boucle traite chaque fichier ZIP situé dans la $filepathvariable

    foreach($file in $filepath)
    {
        $zip = $shell.NameSpace($file.FullName)
        foreach($item in $zip.items())
        {
            $shell.Namespace($file.DirectoryName).copyhere($item)
        }
        Remove-Item $file.FullName
    }
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.