メモリフットプリントを削減する必要がある場合は、使用をスキップしてGet-ChildItem
、代わりに.NETAPIを直接使用できます。Powershell v2を使用していることを前提としています。その場合は、最初にここの手順に従って、 .NET4をPowershellv2にロードできるようにします。
.NET 4には、ファイルとディレクトリを配列で返すのではなく、それらを列挙するための優れたAPIがいくつかあります。
[IO.Directory]::EnumerateFiles("C:\logs") |%{ <move file $_> }
このAPIを使用すると、の代わりに[IO.Directory]::GetFiles()
、一度に1つのファイル名のみが処理されるため、メモリ消費量は比較的少なくなります。
編集
また、のような単純なパイプラインアプローチを試したことがあると想定していましたGet-ChildItem |ForEach { process }
。これで十分なら、私はそれが進むべき道であることに同意します。
しかし、私はよくある誤解を解き明かしたいと思いGet-ChildItem
ます。v2(または実際にはファイルシステムプロバイダー)では、実際にはストリーミングされません。実装ではAPIDirectory.GetDirectories
とDirectory.GetFiles
を使用します。この場合、処理が行われる前に1.6M要素の配列が生成されます。これが完了すると、はい、パイプラインの残りの部分がストリーミングされます。FileInfo
そして、はい、この最初の低レベルの部分は、リッチオブジェクトの配列ではなく、単なる文字列配列であるため、影響は比較的最小限です。O(1)
しかし、このパターンでメモリが使用されていると主張するのは誤りです。
対照的に、Powershellv3は.NET4上に構築されているため、上記(Directory.EnumerateDirectories
およびDirectory.EnumerateFiles
)で説明したストリーミングAPIを利用します。これは素晴らしい変更であり、あなたと同じようなシナリオで役立ちます。