使用PowerShell从zipfile中提取目录的最优雅方式?

Sim*_*raa 9 powershell

我需要从zipfile解压缩一个特定的目录.

例如,从zipfile'c​​:\ tmp\test.zip'中提取目录'test\etc\script',并将其放在c:\ tmp\output\test\etc\script中.

下面的代码有效,但有两个怪癖:

  • 我需要递归地找到zip文件(函数finditem)中的目录('script'),虽然我已经知道了路径('c:\ tmp\test.zip\test\etc\script')

  • 使用CopyHere我需要手动确定目标目录,特别是'test\etc'部分

更好的解决方案?谢谢.

代码:

function finditem($items, $itemname)
{
  foreach($item In $items)
  {
    if ($item.GetFolder -ne $Null)
    {
      finditem $item.GetFolder.items() $itemname
    }
    if ($item.name -Like $itemname)
    {
        return $item
    } 
  } 
} 

$source = 'c:\tmp\test.zip'
$target = 'c:\tmp\output'

$shell = new-object -com shell.application

# find script folder e.g. c:\tmp\test.zip\test\etc\script
$item = finditem $shell.NameSpace($source).Items() "script"

# output folder is c:\tmp\output\test\etc
$targetfolder = Join-Path $target ((split-path $item.path -Parent) -replace '^.*zip')
New-Item $targetfolder -ItemType directory -ErrorAction Ignore

# unzip c:\tmp\test.zip\test\etc\script to c:\tmp\output\test\etc
$shell.NameSpace($targetfolder).CopyHere($item)
Run Code Online (Sandbox Code Playgroud)

Ans*_*ers 10

我不知道最优雅,但安装了.Net 4.5,你可以使用命名空间中的ZipFileSystem.IO.Compression:

[Reflection.Assembly]::LoadWithPartialName('System.IO.Compression.FileSystem') | Out-Null

$zipfile = 'C:\path\to\your.zip'
$folder  = 'folder\inside\zipfile'
$dst     = 'C:\output\folder'

[IO.Compression.ZipFile]::OpenRead($zipfile).Entries | ? {
  $_.FullName -like "$($folder -replace '\\','/')/*"
} | % {
  $file   = Join-Path $dst $_.FullName
  $parent = Split-Path -Parent $file
  if (-not (Test-Path -LiteralPath $parent)) {
    New-Item -Path $parent -Type Directory | Out-Null
  }
  [IO.Compression.ZipFileExtensions]::ExtractToFile($_, $file, $true)
}
Run Code Online (Sandbox Code Playgroud)

的3 的参数ExtractToFile()可以省略.如果存在,它定义是否覆盖现有文件.

  • @jpmc26 OP不想提取zip文件的全部内容. (2认同)

Rom*_*min 7

至于zip中的文件夹位置是已知的,原始代码可以简化:

$source = 'c:\tmp\test.zip'  # zip file
$target = 'c:\tmp\output'    # target root
$folder = 'test\etc\script'  # path in the zip

$shell = New-Object -ComObject Shell.Application

# find script folder e.g. c:\tmp\test.zip\test\etc\script
$item = $shell.NameSpace("$source\$folder")

# actual destination directory
$path = Split-Path (Join-Path $target $folder)
if (!(Test-Path $path)) {$null = mkdir $path}

# unzip c:\tmp\test.zip\test\etc\script to c:\tmp\output\test\etc\script
$shell.NameSpace($path).CopyHere($item)
Run Code Online (Sandbox Code Playgroud)

  • 只是这样其他人不会遇到同样的问题.尝试使用此文件访问nupkg文件时,必须将文件重命名为.zip才能正确解释. (3认同)

Iva*_*kov 6

Windows PowerShell 5.0(包含在Windows 10中)本身支持使用Expand-Archivecmdlet 提取ZIP文件:

Expand-Archive -Path Draft.Zip -DestinationPath C:\Reference
Run Code Online (Sandbox Code Playgroud)

  • 但问题是要求提取zip的子文件夹,特别是. (4认同)
  • ...而Windows 10包括PowerShell 5.0 (3认同)