Powershell退出循环会导致无限递归

时间:2015-11-30 21:09:40

标签: powershell for-loop recursion zip infinite-loop

出于某种原因,下面的powershell代码进入无限循环,我无法弄清楚原因。

最低try块中的代码无法成功,因此我希望catch能够捕获错误,然后继续循环。

然而,它无限循环,创建了越来越多的子目录。

为什么?

在powershell v5.0上测试

尝试包含至少一个子文件夹的文件夹中的代码,该子文件夹本身至少包含一个文件。你会明白我的意思。

Get-ChildItem -Recurse | Where-Object { $_.PSIsContainer} | ForEach-Object {

    $path = $_
    set-Location $path

    #get all items, exclude zip files and folders
    $items = Get-ChildItem -Exclude *.zip | Where-Object { -not $_.psIsContainer}

    #verify that there are items in this directory, catch errors
    if ( $items ) {
        $newfld = New-Item -ItemType Directory -name "blabla"

        #move items to newly-created folder
        Move-Item $items -destination $newfld.Fullname 

        #try to do something that is destined to fail   
        try{
            [void][System.Reflection.Assembly]::LoadFrom($ZipModule)
        }
        catch { 
            Write-Host "No Zip"
        }
    }
}

2 个答案:

答案 0 :(得分:2)

检查$items是否包含任何文件的方法过于复杂,并且行为方式与预期不同。

您可以检查是否只返回任何文件:

if($items){
    # move/zip/create etc.
}

如果Get-ChildItem返回0个文件,则$items将被解释为$false,否则为$true

关于无限循环行为,似乎Get-ChildItem -Recurse在后​​台异步运行,并选择您在此期间创建的blabla文件夹。

您可以通过将来电置于Get-ChildItem -Recurse中来强制ForEach-Object返回()之前的回合:

(Get-ChildItem -Recurse | Where-Object { $_.PSIsContainer}) | ForEach-Object {
    # create/move/zip etc.
}

或者,在循环之前将所有目录(实际上只需要FullName属性)分配给单独语句中的变量:

$Directories = Get-ChildItem -Recurse |Where-Object { $_.PsIsContainer } |Select-Object FullName
foreach($Path in $Directories){
    # create/move/zip etc.
}

答案 1 :(得分:1)

它进入无限循环的原因是因为您要进入子文件夹,检查它是否有文件(非ZIP文件),如果是,请创建一个名为&的新文件夹#34;布拉布拉"并将文件移动到该文件夹​​中。所以代码正在做的是将文件夹中的文件移动到该文件夹​​的子文件夹中,依此类推。如果想要将文件移动到子文件夹然后将其压缩并删除文件,那将停止无限递归。

每次创建子文件夹" blabla"时,都会使递归永久化。