我如何更新此代码以第二次运行但仅在已解压缩的 zip 存档上运行?

Posted

技术标签:

【中文标题】我如何更新此代码以第二次运行但仅在已解压缩的 zip 存档上运行?【英文标题】:How might I update this code to run a second time but only on a zip archive already unzipped? 【发布时间】:2016-11-13 03:06:02 【问题描述】:

这是我目前使用的代码:

# Don't include "\" at the end of $NewSource - it will stop the script from
# matching first-level subfolders
$ignore = "somename"
$files = gci $NewSource -recurse | Where 
    $_.Extension -match "zip||prd" -and $_.FullName -notlike $ignore

foreach ($file in $files) 
    $NewSource = $file.FullName
    # Join-Path is a standard Powershell cmdLet
    $destination = Join-Path (Split-Path -Parent $file.FullName) $file.BaseName
    Write-Host -Fore green $destination
    $destination = "-o" + $destination
    # Start-Process needs the path to the exe and then the arguments passed
    # separately. You can also add -wait to have the process complete before
    # moving to the next
    Start-Process -FilePath "C:\Program Files\7-Zip\7z.exe" -ArgumentList "x -y $NewSource $destination" -Wait

但是,一旦完成,我需要返回新目录并解压缩我的 .prd 文件,这些文件是在解压缩 .zip 档案后创建的。在这里需要一些帮助,因为我的尝试不起作用,目前解压缩并覆盖所有以前解压缩的 .prd 和 .zip 文件。

【问题讨论】:

【参考方案1】:

我already told you 认为$_.Extension -match "zip||prd" 匹配all 扩展名,因为正则表达式中两个| 字符之间的空字符串(所有字符串都包含空字符串)。

此外,-notlike-like 运算符的行为与 -ne-eq 运算符在将值与其中没有 wildcards 的模式进行比较时完全相同,因此您的第二个条件将匹配所有全名不是确切“somename”的文件。

改变这个:

$ignore = "somename"
$files = gci $NewSource -recurse | Where 
    $_.Extension -match "zip||prd" -and $_.FullName -notlike $ignore

进入这个:

$ignore = "*somename*"
$files = gci $NewSource -recurse | Where 
    $_.Extension -match "zip|prd" -and $_.FullName -notlike $ignore

并且代码应该符合您的预期。

作为替代方案,您可以构建一个您想要忽略的路径列表

$ignore = 'C:\path\to\first.zip',
          'C:\other\path\to\second.zip',
          'C:\some\file.prd',
          ...

并使用-notin(PowerShell v3 或更新版本)或-notcontains 运算符排除这些文件:

$_.FullName -notin $ignore
$ignore -notcontains $_.FullName

作为旁注,我会使用call operator 和splatting 而不是Start-Process 来调用7zip.exe

$destination = Join-Path (Split-Path -Parent $file.FullName) $file.BaseName
$params      = 'x', '-y', $NewSource, "-o$destination"
& "$env:ProgramFiles\7-Zip\7z.exe" @params

要同时提取从 zip 存档中提取的 .prd 文件,请在循环中添加另一个步骤。

foreach ($file in $files) 
    ...
    & "$env:ProgramFiles\7-Zip\7z.exe" @params
    Get-ChildItem $destination | Where-Object 
        $_.Extension -eq 'prd'
     | ForEach-Object 
        # extract matching file here, procedure is the
        # same as with the files in the outer loop
    

您可能希望将用于构建目标路径和提取文件的代码封装在一个函数中,该函数读取路径 from the pipeline 并在目标路径包含 .prd 文件时递归调用自身。

function Invoke-Unzip 
    [CmdletBinding()]
    Param(
        [Parameter(
            Mandatory=$true,
            ValueFromPipeline=$true,
            ValueFromPipelineByPropertyName=$true
        )]
        [ValidateScript(Test-Path -LiteralPath $_)]
        [string]$FullName
    )

    $newSource = $FullName
    ...
    & "$env:ProgramFiles\7-Zip\7z.exe" @params
    Get-ChildItem $destination |
        Where-Object  $_.Extension -eq 'prd'  |
        Invoke-Unzip

【讨论】:

这个答案虽然总体上改进了我的代码,但并没有回答我发布的问题。 @Underdog 现在可以了。

以上是关于我如何更新此代码以第二次运行但仅在已解压缩的 zip 存档上运行?的主要内容,如果未能解决你的问题,请参考以下文章

运行时错误,但仅在第二个循环中

UseState 仅在第二次单击时显示

Android - Singleton Class仅在第二次刷新时更新

Apollo 客户端 writeQuery 更新存储,但 UI 组件仅在第二次函数调用后更新

useState 在第二次点击时更新状态

Mongoose:批量更新插入,但仅在满足某些条件时才更新记录