Memory 使用大量内存的文件夹中的PowerShell foreach文件

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

我对PowerShell和编程相当陌生,因此我相信这段代码可以进行更多优化

然而,这段代码最大的问题是它将来自foreach循环的数据放在内存中。预防这种情况的最佳方法是什么

我从我在这里找到的脚本开始重写此脚本:

编辑:哦,顺便说一下,每个TargetFolder中大约有60000个文件

## 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" }