如何在Powershell中解压缩文件?


224

我有一个.zip文件,需要使用Powershell解压缩其全部内容。我正在这样做,但似乎不起作用:

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

怎么了?该目录C:\a仍然为空。


6
如果您使用的是Powershell 2.0,或者未安装.NET 4.5,则您提到的方法是唯一的途径(无需使用第三方exe(即7zip)。我想说,直到有人提供了为什么这种方法行不通的方法。它在某些时候对我
有用

Answers:


248

下面是一个使用简单的方法ExtractToDirectorySystem.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"

请注意,如果目标文件夹不存在,ExtractToDirectory将创建它。其他警告:

也可以看看:


10
为什么要创建一个函数来替换单个函数调用?

17
从理论上讲,您不需要。我试图在函数中隐藏复杂/非常规的调用,以便以后可以替换该方法而不必担心它的使用位置。正如Keith所提到的,在V5中将有一种新的方式来实现它。
米奇·巴拉德利

1
为此,您至少需要.NET Framework 4.5。请参阅msdn.microsoft.com/en-us/library/…
ferventcoder '16

10
我尝试了此操作,但遇到了以下错误, 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 '16

4
这给我以下错误:Add-Type : Cannot add type. The assembly 'System.IO.Compression.FileSystem' could not be found.。我已经安装了.NET 4.6.2,并且已经验证了该程序集在GAC中,但我不知道为什么会出现此错误。
山姆

500

在PowerShell v5 +中,内置有一个Expand-Archive命令(以及Compress-Archive):

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

26
使用$PSVersionTable.PSVersion以确定你正在运行的PowerShell版本。
Brad C

1
@LoneCoder我认为你不能怪鲍尔默。Windows 从来没有内置的命令行工具来处理压缩文件,即使gzip于1992年问世,而tar更早。
jpmc26 2013年

2
发布此答案时,甚至Windows 10和Server 2012以下的版本都无法使用@Ghashange PowerShell 5,即使是预发行版也是如此。
jpmc26 2013年

11
像参数看起来OutputPath已更改为DestinationPath(参考msdn.microsoft.com/powershell/reference/5.1/...
伊利亚W.加涅

1
您也可以使用相对路径,例如Expand-Archive -Path .\a.zip -DestinationPath .
Culip

24

在PowerShell v5.1中,这与v5略有不同。根据MS文档,它必须具有一个-Path参数来指定存档文件路径。

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

否则,这可能是实际路径:

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

扩展存档文档


3
此Cmdlet中的v5和v5.1之间没有区别。您无需命名第一个参数。它会自动成为路径。例如,Expand-Archive Draft.Zip -DestinationPath C:\Reference没有问题的作品。另外,它不是实际路径,而是绝对路径。
富兰克林于

13

Expand-Archivecmdlet与参数集之一一起使用:

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

12

嘿,它为我工作。

$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
如果目标位置已存在一个文件或目录,它将弹出一个对话框,询问该做什么(忽略,覆盖),这将使目标无效。有谁知道如何强制它默默覆盖?
奥列格·卡扎科夫

回答@OlegKazakov的评论:有一组控制该CopyHere方法的选项。我猜@OlegKazakov已经解决了他的问题。尽管如此,我还是将此链接放在此处以找到可以找到此主题的其他冲浪者:docs.microsoft.com/en-us/previous-versions/windows/desktop/…–
jsxt

4

对于那些想要使用Shell.Application.Namespace.Folder.CopyHere()并在复制时隐藏进度条或使用更多选项的用户,此文档位于:https :
//docs.microsoft.com/zh-cn / windows / desktop / shell / folder-copyhere

要使用powershell并隐藏进度条并禁用确认,可以使用如下代码:

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

在Windows核心版本上使用Shell.Application的限制:https :
//docs.microsoft.com/zh-cn/windows-server/administration/server-core/what-is-server-core

在Windows 核心版本上,默认情况下未安装Microsoft-Windows-Server-Shell-Package,因此shell.applicaton将不起作用。

注意:以这种方式提取档案将花费很长时间,并且会减慢Windows gui的运行速度。


3

使用expand-archive但自动创建以存档命名的目录:

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

这一定会在当前目录中扩展,不是吗?
jpmc26,2017年

真的看不到自动创建的附加值。outputPath像接受的答案一样添加第二个参数更加灵活。在此解决方案中(如jpmc26所说),您将始终在当前目录中创建一个新目录,因此有可能需要在调用之前设置当前目录unzip
Rubanov

大多数存档器都在与存档相同的位置提取到以存档命名的目录中。如果您希望有所不同,没有什么可以阻止您添加参数的,但这是明智的默认选择。
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)
    }
}

使用:

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

不要忘了处置,$archive$archiveFile在最后
tom.maruska

0

ForEach循环处理位于$filepath变量内的每个ZIP文件

    foreach($file in $filepath)
    {
        $zip = $shell.NameSpace($file.FullName)
        foreach($item in $zip.items())
        {
            $shell.Namespace($file.DirectoryName).copyhere($item)
        }
        Remove-Item $file.FullName
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.