Not tested, but this should be easier on your memory load:
#Script to clean up the OrchestriaCache NAS
$pwdZ = 'c:\temp\test\'
$zip = 'c:\temp\7z.exe'
$dest = 'c:\temp\zip'
#$a = get-childitem $pwdZ -recurse | where-object {$_.PSISContainer -eq $true}
#$b = $a | where-object {$_.GetFiles().Count -ge 1} #| select-object FullName
$b = cmd /c dir $pwdZ /b /s /ad |
where-object {([IO.Directory]::GetFiles($_)).Count -ge 1}
#write-host $b.FullName
write-host $b
$ctr = 0
$cnt = $b.Count
$b | foreach-object {
$ctr++
write-host $('[' + $ctr + '\' + $cnt + '] Zipping: ' + $_) -foregroundcolor red
$Name = $_.split('\')[-1]
move-item -path $($_ + '\*.*') -force -destination $dest
cmd /c $('"c:\temp\7z.exe a ' + $($_ + '\' + $Name + '.zip') + ' '+ $($dest + '\*"'))
}
The legacy dir command is much faster and less memory intensive than get-childitem for large directory structures. The /b /s /ad switches will make it recurse and return only the fullname strings of the directories.
The intermediate variable $a holding the complete list of directories is eliminated by filtering the folders that don't contain files as they come in. The name is parsed from that by splitting on the backslashes and taking the last element. You could refine this a little further by making your zip routine a filter or pipeline function so that you start zipping files as soon as you find a directory that has files in it. If you add additional code to save a list of directories you've already zipped, or check for the presence of a .zip file already in the directory it can be made to be re-startable.