Powershell:递归计算文件而忽略特定目录

时间:2015-11-13 18:00:49

标签: powershell recursion count directory ignore

我正在尝试设置某些文件夹中包含50多个文件的警报。文件夹目录是:

C:\Application\CustomerID\oneDirectory\RegisterName\transactions\FilesToCount

对于oneDirectory,有多个我不关心 - 我只关心oneDirectory。我还关注多个RegisterNames。对于transactions,还有其他多个我不关心的目录。对于CustomerID,我还关注多个其他目录(客户)

基本上,我需要为每个客户的每个寄存器计算transactions文件夹中的文件数,而忽略所有其他文件夹。如果任何一个客户有超过50个左右的文件,我需要收到一封电子邮件告诉我。我还需要忽略.ini个文件。

现在,我有以下脚本可以正常工作,并且从上面执行所需的功能,但运行时间太长,我无法弄清楚原因:

$mainFolder = "C:\Application\Customer."
$tenantID = "CustomerID"
$maxTenantID = "HighestCustomerID"
$registerPath = "\oneDirectory\"

while($tenantID -le $maxTenantID) {

    $loc = $mainFolder + $tenantID + $registerPath

    $ignore = @("failed_transactions", "saved_transactions", "temp", "offline_logs", "pos_logs", "pos_reports")

    $files = Get-ChildItem -Path $loc -Recurse  -Exclude *.ini | ? { !$_.PSIsContainer } | % {

        $relative = $_.FullName.Replace($loc, "")
        $nomatch = $true

        foreach ($folder in $ignore) {
            if($relative -like "*\$folder\*") {
                $nomatch = $false
            }
        }

        if ($nomatch) { $_ }
    }

    $currentCount = $files.Count    
    if($currentCount -gt 50) {
        Send-MailMessage -From "email@whatever.com" -To "email@whatever.com" -SmtpServer "smtp.whatever.com" -Subject "Transactions stuck" -Body "$loc has over 50 transactions."
    }

    $tenantID++
}

如前所述,上面的代码正在正确地完成工作,但我正在尝试设置一个计划任务来每小时运行一次。在测试期间,这需要一个多小时才能完成。我甚至将它分成三个脚本,每个脚本占客户列表的1/3,但仍然需要永久。

我不确定它背后的逻辑是否是问题,或者它是否只是效率不高。这是我的第一个powershell脚本,所以我不知道从哪里开始。

1 个答案:

答案 0 :(得分:0)

如果它真的是你的第一个PS剧本,这是一个非常好的第一枪:)。

提示:每次在另一个循环中嵌套循环时,都应该使用制表符缩进它。您也可以将;留在PS ^^中(除了在同一行上有多个语句) - 我会编辑您的帖子,如果我可以 - 完成,还添加了一个缺少的双引号消息正文的结尾

我尽可能地尽量简化。

是否可以尝试在配置中使用适当的值运行此操作,并查看结果是否为每位客户提供了正确的卡住交易计数?

我会根据需要尝试改进。

编辑:也许正在减慢你速度的是邮件发送步骤:)在第一次测试期间将其注释掉

#config
$mainFolder = "C:\Application\Customer."
$tenantID = 0 # test value
$maxTenantID = 2 # test value
$registerPath = "oneDirectory"

#initialize results array
$results = @()

#iterate through customers
while($tenantID -le $maxTenantID) {

    #build Path
    $loc = Join-Path $mainFolder$tenantID $registerPath

    #list files (excluding .ini)
    $files = Get-ChildItem -Path $loc -Recurse -Exclude "*.ini" |
        Where-Object { !$_.PSIsContainer }

    #reset counter
    $stuckCount = 0

    #iterate through files    
    foreach($file in $files) {

        #split path to get parent and ancestor        
        $parent = Split-Path $file.Directory -Leaf
        $ancestor = Split-Path $file.Directory.Parent.Parent -Leaf

        #if ancestor is oneDirectory and parent is transactions
        if(($ancestor -eq "oneDirectory") -and ($parent -eq "transactions")) {

            #increment counter
            $stuckCount++
        }
    }

    #create a custom object with customer name and stuck transactions count, and add it to the results array
    $results += [PSCustomObject]@{ Customer = $tenantID ; StuckCount = $stuckCount }

    if($stuckCount -gt 50) {
        #uncomment to send a mail if stuck transation count is over 50 for this customer
        #Send-MailMessage -From "email@whatever.com" -To "email@whatever.com" -SmtpServer "smtp.whatever.com" -Subject "Transactions stuck" -Body "$loc has over 50 transactions."
    }

    #increment customer ID
    $tenantID++
}

#output results array
$results

#example output :
#Customer StuckCount
#-------- -----------
#       0          58
#       1         110
#       2          13

#you could also send a global mail report here using $results array, for example :
#
#$results | ? { $_.StuckCount -gt 50 }
#
#will only list the customers with a stuck transaction count over 50