Powershell退出循环导致无限递归

Powershell exiting loop causes infinite recursion

由于某些原因,下面的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"
        }
    }
}

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

您可以检查是否有任何文件 returned 只用:

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

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


关于无限循环行为,Get-ChildItem -Recurse 似乎在后台异步保持 运行 并获取您同时创建的 blabla 文件夹。

您可以通过将调用包含在 ():

中,在管道传输到 ForEach-Object 之前强制 Get-ChildItem -Recurse 到 return
(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.
}

它进入无限循环的原因是因为你要进入一个子文件夹,检查它是否有文件(非 ZIP 文件),如果有,创建一个名为 "blabla" 的新文件夹并将文件移动到该文件夹​​中。所以代码所做的是不断将文件夹中的文件移动到该文件夹​​的子文件夹中,等等。如果您的想法是将文件移动到子文件夹中,然后将其压缩并删除文件,那将停止无限递归。

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