繁体   English   中英

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

[英]Powershell 2.0 extract certain files from zip (include subdirectories)

抱歉,这个问题分散在互联网上,但我还没有找到一个令人满意的答案,它只使用 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位于子目录\Subfolder\log.txt中,则失败
  • 如果引用文字 (.zip) 路径{$_.Name -Like '*Subfolder\log.txt'}则失败(双引号和单引号均失败)
  • 尝试使用-eq -like -contains '' "" $_.FullName

我很确定我过滤不正确 - 任何人都可以帮助处理这段代码,以便它也能解析子目录吗?

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

$zipFilePath = "Zipfile.zip"
$destinationPath = "C:\Users\Public\Downloads"

$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:\Users\Public\Downloads"

Get-ZipChildItems -ZipFile $zipFilePath -DestinationPath $destinationPath

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM