Это можно сделать?Удалить огромное количество файлов в зависимости от того, сколько лет они используют Powershell - PullRequest
0 голосов
/ 31 января 2019

На сервере под управлением Windows 2012 R2, версия

PS C:\Users\admin> $PSVersionTable.PSVersion
Major  Minor  Build  Revision
-----  -----  -----  --------
4      0      -1     -1

Мне нужно удалить файлы старше 180 дней в папке с большим количеством подпапок.Это довольно просто, НО не тогда, когда существуют сотни тысяч файлов и папка размером около 800 ГБ.Использование Get-ChildItem, который сначала рекурсивно читает все файлы при проверке даты, а затем начинает их удалять ... ну, это занимает вечно, а серверу в конце не хватило памяти.

Итак - любой, кто хочет помочь мне ускорить мой код, текущая скорость которого такова (часть удаления)

...
...
foreach ($i in Get-ChildItem $TargetFolder -recurse -exclude 
 $skipFilePatterns | where { ! $i.PSIsContainer }) { 

if (! $i.PSIsContainer -and $i.LastWriteTime -lt ($(Get-Date).AddDays(-$keepForDays))) { 
    # Add -WhatIf to test the script, remove it when confirmed
    $timeStamp = $i.LastWriteTime
    $fullName = $i.FullName
    $log.Info("Deleting: $fullName with timestamp (LastWriteTime): $timeStamp")


    Remove-Item $i.FullName -force -ErrorVariable errVar -ErrorAction SilentlyContinue 
...
...

Ответы [ 2 ]

0 голосов
/ 31 января 2019

Таким образом, вы можете использовать Select -first $Limit

Во-вторых, не нужно исключать папки $i.PSIsContainer Вы можете просто указать Get-ChildItem (псевдоним GCI), чтобы получать файлы только с использованием -File param

Что-то вроде

function Remove-ChildItemsInChunks($keepForDays, $Limit, $Path){
    $count = 0
    gci $Path -Recurse -File | 
        ?{$i.LastWriteTime -lt ($(Get-Date).AddDays(-$keepForDays))} |
        select -First $Limit | %{
            $count += 1
            Remove-Item $_
        }
    return $Count
}


$GCICount = Get-ChildItemsInChunks -Path C:\test -keepForDays 30 -Limit 500
while($GCICount -gt 0){
    $GCICount = Get-ChildItemsInChunks -Path C:\Test -keepForDays 30 -Limit 500
}
0 голосов
/ 31 января 2019

Я бы посоветовал использовать конвейер до конца, иначе вы сначала соберете все в памяти.Использование регулярных выражений, вероятно, было бы более эффективным в фильтре Where-Object, чем использование -Exclude (что, как известно, неэффективно).

$limit = (Get-Date).AddDays(-180)
$skipFilePatterns = @() # probably some collection of wildcard strings

Get-ChildItem -Recurse -File -Exclude $skipFilePatterns |
    Where-Object LastWriteTime -lt $limit |
    ForEach-Object {
        $timeStamp = $PSItem.LastWriteTime.ToString('o') # ISO-8601-compliant string
        $fullName = $PSItem.FullName
        $log.Info("Deleting: $fullName with timestamp (LastWriteTime): $timeStamp")
        $PSItem
    } | Remove-Item -Force -ErrorVariable errVar -ErrorAction SilentlyContinue
...