Powershell 2.0从zip中提取某些文件(包括子目录)



抱歉,这个问题分散在互联网上,但我还没有找到一个满意的答案,只使用Powershell 2.0(带有.NET v3.5(-没有外部库或程序

我使用以下代码从ZipFile.zip(无论log.txt的位置如何(中提取log.txt

$Destination = (new-object -com shell.application).NameSpace('C:ZipExtractDir')
$ZipFile = (new-object -com shell.application).NameSpace('C:ZipFile.zip')
$Destination.CopyHere(($Zipfile.Items() | where-object {$_.Name -like '*log.txt'}), 1044)
  • 如果log.txt在根目录log.txt中则有效
  • 如果log.txt在子目录Subfolderlog.txt中,则失败
  • 如果引用文本(.zip(路径,则失败{$_.Name -Like '*Subfolderlog.txt'}(双引号和单引号都失败(
  • 尝试使用-eq-like-contains''""$_.FullName

我很确定我过滤错误了——有人能帮我处理这段代码吗?这样它也能解析子目录吗?

与您已经做的类似,您可以像这样设置Shell.Application名称空间。然后,您可以将提取的目录复制到目标路径。

$zipFilePath = "Zipfile.zip"
$destinationPath = "C:UsersPublicDownloads"
$zipfile = (New-Object -Com Shell.Application).NameSpace($zipFilePath)
$destination = (New-Object -Com Shell.Application).NameSpace($destinationPath)
$destination.CopyHere($zipfile.Items())

然后为了列出log.txt文件,我们可以用Join-Path构造完整的提取路径。这基本上只是将来自System.IO.Path.GetFileNameWithoutExtension()的zip文件名附加到目标路径。然后只需使用Get-ChildItem通过-Recurse-Filter开关递归地列出文件。

$extractedPath = Join-Path -Path $destinationPath -ChildPath ([System.IO.Path]::GetFileNameWithoutExtension($zipFilePath))
Get-ChildItem -Path $extractedPath -Filter log.txt -Recurse

为了在PowerShell 2.0中测试这一点,我们可以将-version 2powershell.exe:一起使用

powershell.exe -version 2 .test.ps1

更新

如果你想在提取之前检查文件,你需要自己递归目录。下面是如何做到这一点的演示。

function New-ZipChildRootFolder 
{
param 
(
[string]$DestinationPath,
[string]$ZipFileName
)
$folderPath = Split-Path -Path $ZipFileName -Leaf
$destination = (New-Object -ComObject Shell.Application).NameSpace($DestinationPath)
$destination.NewFolder($folderPath)
}
function Get-ZipChildItems 
{
param 
(
[string]$ZipFilePath,
[string]$DestinationPath
)
$zipfile = (New-Object -ComObject Shell.Application).NameSpace($ZipFilePath)
$zipFileName = [System.IO.Path]::GetFileNameWithoutExtension($ZipFilePath)
Write-Output "Create root zip folder : $zipFileName"
New-ZipChildRootFolder -DestinationPath $DestinationPath -ZipFileName $zipFileName
foreach ($item in $zipFile.items()) 
{
Get-ZipChildItemsRecurse -Items $item -DestinationPath $DestinationPath -ZipFileName $zipFileName
}
}
function Get-ZipChildItemsRecurse
{
param 
(
[object]$Items,
[string]$DestinationPath,
[string]$ZipFileName
)
foreach ($file in $Items.getFolder.Items())
{
if ($file.IsFolder -eq $true) 
{
Write-Output "Creating folder : $($file.Path)"
New-ZipChildFolder -Folder $file -DestinationPath $DestinationPath -ZipFileName $ZipFileName
Get-ZipChildItemsRecurse -Items $file -DestinationPath $DestinationPath -ZipFileName $ZipFileName
}
else 
{
$filename = Split-Path -Path $file.Path -Leaf
if ($filename -eq "log.txt")
{
Write-Output "Copying file : $($file.Path)"
New-ZipChildFile -File $file -DestinationPath $DestinationPath -ZipFileName $ZipFileName
}
}
}
}   
function New-ZipChildFile
{
param
(
[object]$File,
[string]$DestinationPath,
[string]$ZipFileName
)
$destination = New-Object -ComObject Shell.Application
$items = $File.Path.Split("")
$zipRootIndex = [array]::IndexOf($items, $ZipFileName)
$path = $items[$zipRootIndex..($items.Length - 2)] -join ""
$fullPath = Join-path -Path $DestinationPath -ChildPath $path
$destination.NameSpace($fullPath).CopyHere($File)
}
function New-ZipChildFolder
{
param 
(
[object]$Folder,
[string]$DestinationPath,
[string]$ZipFileName
)
$destination = New-Object -ComObject Shell.Application
$items = $Folder.Path.Split("")
$zipRootIndex = [array]::IndexOf($items, $ZipFileName)
$folders = $items[$zipRootIndex..($items.Length - 1)]
$currentFolder = $DestinationPath
foreach ($folder in $folders)
{
$destination.NameSpace($currentFolder).NewFolder($folder)
$currentFolder = Join-Path -Path $currentFolder -ChildPath $folder
}
}

用法:

$zipFilePath = "C:Zipfile.zip"
$destinationPath = "C:UsersPublicDownloads"
Get-ZipChildItems -ZipFile $zipFilePath -DestinationPath $destinationPath

最新更新