Memory 使用大量内存的文件夹中的PowerShell foreach文件
我对PowerShell和编程相当陌生,因此我相信这段代码可以进行更多优化 然而,这段代码最大的问题是它将来自foreach循环的数据放在内存中。预防这种情况的最佳方法是什么 我从我在这里找到的脚本开始重写此脚本: 编辑:哦,顺便说一下,每个TargetFolder中大约有60000个文件Memory 使用大量内存的文件夹中的PowerShell foreach文件,memory,powershell,foreach,Memory,Powershell,Foreach,我对PowerShell和编程相当陌生,因此我相信这段代码可以进行更多优化 然而,这段代码最大的问题是它将来自foreach循环的数据放在内存中。预防这种情况的最佳方法是什么 我从我在这里找到的脚本开始重写此脚本: 编辑:哦,顺便说一下,每个TargetFolder中大约有60000个文件 ## Set Window Title $title = $Host.UI.RawUI.WindowTitle $titdef = $title $Host.UI.RawUI.WindowTitle = "C
## 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
这个版本有效。感谢所有帮助过我的人
## 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
尝试:
编辑 我现在明白了,您的问题是由于
包括!如果需要使用通配符和nor正则表达式来获取子项,请改用filter
。由于不使用正则表达式匹配,因此性能更高
尝试:
$Folder1=获取子项$TargetFolder1-筛选器*
即使你不太清楚你在那里过滤什么(或者你想包括什么)…一切?也许你根本不需要通配符
在我看来,防止内存中foreach循环的最好方法是管道。但是,由于脚本的性质(循环中有许多嵌套控件),这并不容易
尝试:
$Folder1 | % {
# ...
}
$Folder1 |%{
# ...
}
即使我怀疑它会提高性能
或:
获取子项$TargetFolder1-包括*|%{
# ...
}
差不多
$TS=(Get-Date).AddDays(-2)
$COUNT = (get-childitem -recurse path1,path2 |where-object {$_.LastWriteTime -gt $TS}|measure-object).Count
if ($COUNT > 0) { Echo "There are $COUNT files" }
可能更好(我还没有测试过它的性能)一个好的重构(使用函数,更好的日志系统…)应该让它更容易。你的意思是我应该用你以后的建议替换我的foreach循环吗?这会不会在所有文件中循环,当它结束时,首先会清除内存?我正在尝试查找是否有超过2天的新文件。否则,将文件放入其中的应用程序已崩溃。它们是XML文件。所以这可能是解决问题的方法?get-childitem$TargetFolder2-filter*.xmlI将foreach循环替换为$FolderX |%{}和-include with-filter。它仍在使用200MB+的数据,而且仍然需要很长时间才能完成。(10分钟~)尝试getchilditem$TargetFolder1-filter*.xml |%{
否则你真的需要按照@Cedric的建议重构你的代码。谢谢,这似乎优化得更好。但我并没有试图删除文件:)我只是想知道是否有超过2天的新文件,如果没有,我会收到电子邮件或其他通知。对不起,我刚才看到你提到删除文件,并且没有正确检查这就是你想要的!不管怎样,你现在对empo的答案很满意。现在更新代码,只需计算匹配的文件并测试答案。你的版本非常精简-我喜欢。尽管很难接受两个版本的答案:-\
$Folder1 = get-childitem $TargetFolder1 -filter *
$Folder1 | % {
# ...
}
get-childitem $TargetFolder1 -include * | % {
# ...
}
$TS=(Get-Date).AddDays(-2)
$COUNT = (get-childitem -recurse path1,path2 |where-object {$_.LastWriteTime -gt $TS}|measure-object).Count
if ($COUNT > 0) { Echo "There are $COUNT files" }