1

私の問題はPowershellにあります。私は非常に大きなフォルダを持っています。インサイダーは約160万のサブフォルダーです。私の仕事は、6か月以上経過した空のフォルダまたはその下のファイルをすべて消去することです。foreachを使用してループを作成しましたが、PowerShellがループを開始するまでには何年もかかります->

..。

foreach ($item in Get-ChildItem -Path $rootPath -recurse -force | Where-Object -FilterScript { $_.LastWriteTime -lt $date })
{
# here comes a script which will erase the file when its older than 6 months
# here comes a script which will erase the folder if it's a folder AND does not have child items of its own

..。

問題:内部メモリがいっぱいになり(4GB)、正しく動作しなくなりました。私の推測では、PowerShellは1 600 000個のフォルダーをすべてロードし、その後でのみそれらのフィルター処理を開始します。

これを防ぐ可能性はありますか?

4

1 に答える 1

0

正解です。すべての160万個のフォルダ、または少なくともそれらへの参照が一度に読み込まれます。ベストプラクティスは、左にフィルタリングして右にフォーマットすることです。IOW、Where-Object可能であれば、ヒットする前にこれらのフォルダーを削除してください(残念ながら、gci日付フィルターAFAICTはサポートされていません)。また、パイプラインに物事を保持すると、使用するメモリが少なくなります。

以下は、条件に一致するフォルダーのみに制限$itemsし、それらのオブジェクトに対してループを実行します。

$items = Get-ChildItem -path $rootpath -recurse -force | ?{ $_.LastWriteTime -lt $date }
foreach ($item in $items) {
# here comes a script which will erase the file when its older than 6 months
# here comes a script which will erase the folder if it's a folder AND does not have child items of its own
}

またはさらに合理化:

function runScripts {
    # here comes a script which will erase the file when its older than 6 months. Pass $input into that script. $input will be a folder.
    # here comes a script which will erase the folder if it's a folder AND does not have child items of its own Pass $input into that script. $input will be a folder.
}
Get-ChildItem -path $rootpath -recurse -force | ?{ $_.LastWriteTime -lt $date }|runScripts

この最後のケースでrunScriptsは、パイプライン化されたオブジェクトを操作可能なパラメーターとして使用する関数として使用している$inputため、これらの中間オブジェクトを使用する代わりに、パイプラインを介してすべてを送信できます(より多くのメモリを消費します)。

于 2012-09-10T14:23:23.760 に答える