Question:
I’m fairly new to PowerShell and programming, so I’m sure this code can be optimized even more.
However, my biggest problem with this code is that it puts it’s data from the foreach loop in memory. What is the best way to prevent this?
I started up rewriting this script from a script that I found here: PowerShell: delete files older than x days
Edit: Oh, there is about 60 000~ files in each TargetFolder by the way.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
## Set Window Title $title = $Host.UI.RawUI.WindowTitle $titdef = $title $Host.UI.RawUI.WindowTitle = "Checking files. Do NOT close " + "($title)" ## Debug (0=Nothing, 1=Extended log, 2=Extended log+Screen) $Debug = "2" ## Log file $log = "C:\status\status.txt" Add-Content $log "nul" ## Clear log before adding new data Remove-Item $log ## Folders to check $TargetFolder1 = “\\server\c$\BiztalkProjects\UDC\output\ume” $TargetFolder2 = “\\server\c$\BiztalkProjects\UDC\output\upp” ## Required stuff $Now = Get-Date $Days = “2” $TwoDays = $Now.AddDays(-$Days) $Folder1 = get-childitem $TargetFolder1 -include * $Folder2 = get-childitem $TargetFolder2 -include * ## Window Message "Checking for files newer than $Days days in:" "$TargetFolder1" "$TargetFolder2" "" "This may take 5-15 minutes . . . (Will commit about 250MB~ RAM during the period)" ## Reset variable $OK to "0" $OK = 0 if ($Debug -eq "2") {"Check1"} foreach ($File in $Folder1) { $FileLastWrite = $File.LastWriteTime if ($File.LastWriteTime -le $TwoDays) { $OK = $OK + "0" if ($Debug -eq "2") { "OK + 0 (=$OK) $File ($FileLastWrite)" } } else { $OK = $OK + "1" if ($Debug -eq "2") { "OK + 1 (=$OK) $File ($FileLastWrite)" } } } if ($Debug -eq "2") {"Check2"} foreach ($File in $Folder2) { $FileLastWrite = $File.LastWriteTime if ($File.LastWriteTime -le $TwoDays) { $OK = $OK + "0" if ($Debug -eq "2") { "OK + 0 (=$OK) $File ($FileLastWrite)" } } else { $OK = $OK + "1" if ($Debug -eq "2") { "OK + 1 (=$OK) $File ($FileLastWrite)" } } } if ($OK -gt "0") { if ($Debug -eq "2") { "" "Found $OK file(s) newer than $Days days" } Add-Content $log "OK" if ($Debug -ge "1") { Add-Content $log "Found $OK file(s) newer than $Days days" } } else { if ($Debug -eq "2") { "" "Found $OK file(s) newer than $Days days" } Add-Content $log "Error" if ($Debug -ge "1") { Add-Content $log "Found $OK file(s) newer than $Days days" } } $Host.UI.RawUI.WindowTitle = $titdef |
This version works. Thanks to all who helped!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
## Set Window Title $title = $Host.UI.RawUI.WindowTitle $titdef = $title $Host.UI.RawUI.WindowTitle = "Checking files. Do NOT close " + "($title)" ## Debug (0=Nothing, 1=Extended log, 2=Extended log+Screen) $Debug = "2" ## Log file $log = "C:\status\status.txt" Add-Content $log "nul" ## Clear log before adding new data Remove-Item $log ## Folders to check $TargetFolder1 = “\\server\c$\BiztalkProjects\UDC\output\ume” $TargetFolder2 = “\\server\c$\BiztalkProjects\UDC\output\upp” ## Required stuff $Now = Get-Date $Days = “2” $TwoDays = $Now.AddDays(-$Days) ## Window Message "Checking for files newer than $Days days in:" "$TargetFolder1" "$TargetFolder2" "" "This may take 5-15 minutes . . ." ## Reset variable $OK to "0" $OK = 0 get-childitem $TargetFolder1,$TargetFolder2 -filter *.xml |where-object { $FileLastWrite = $_.LastWriteTime if ($FileLastWrite -le $TwoDays) { $OK = $OK + "0" } else { $OK = $OK + "1" } } if ($OK -gt "0") { if ($Debug -eq "2") { "" "Found $OK file(s) newer than $Days days" } Add-Content $log "OK" if ($Debug -ge "1") { Add-Content $log "Found $OK file(s) newer than $Days days" } } else { if ($Debug -eq "2") { "" "Found $OK file(s) newer than $Days days" } Add-Content $log "Error" if ($Debug -ge "1") { Add-Content $log "Found $OK file(s) newer than $Days days" } } $Host.UI.RawUI.WindowTitle = $titdef |
Answer:
Try:
1 |
$Folder1 = get-childitem $TargetFolder1 -filter *.xml |
Much more performant than using include
(on a large set of files). Or even better:
1 |
get-childitem $TargetFolder1 -filter *.xml | % {} |
EDIT
I see now, your problems are due to include
! If you need to use wildcards and nor regular expressions to get the child item, use filter
instead. Is much more performant because does not use regular expression matching.
Try:
1 |
$Folder1 = get-childitem $TargetFolder1 -filter * |
even if it’s not very clear what you are filtering there (or you want include)…everything? May be you don’t need the wildcard at all.
In my humble opinion, the best way to prevent foreach loop in memory is piping. However, due to the nature of your script (many nested controls inside the loop) it’s not that easy.
Try with:
1 2 3 |
$Folder1 | % { # ... } |
even if I doubt it will improve performances.
or:
1 2 3 |
get-childitem $TargetFolder1 -include * | % { # ... } |