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",您都在使递归永久化。
由于某些原因,下面的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",您都在使递归永久化。