如何使用Powershell管道来避免大型对象?
我使用一个自定义函数在8TB驱动器(数千个文件)上执行DIR命令(递归文件列表) 我的第一次迭代是:如何使用Powershell管道来避免大型对象?,powershell,export-to-csv,pipeline,Powershell,Export To Csv,Pipeline,我使用一个自定义函数在8TB驱动器(数千个文件)上执行DIR命令(递归文件列表) 我的第一次迭代是: $results = $PATHS | % {Get-FolderItem -Path "$($_)" } | Select Name,DirectoryName,Length,LastWriteTime $results | Export-CVS -Path $csvfile -Force -Encoding UTF8 -NoTypeInformation -Delimiter "|" 这
$results = $PATHS | % {Get-FolderItem -Path "$($_)" } | Select Name,DirectoryName,Length,LastWriteTime
$results | Export-CVS -Path $csvfile -Force -Encoding UTF8 -NoTypeInformation -Delimiter "|"
这导致了一个巨大的$results变量,并通过在处理过程中增加powershell进程的峰值以使用99%-100%的CPU,将系统拖慢到爬行状态
我决定使用管道的强大功能直接写入CSV文件(可能会释放内存),而不是保存到中间变量,并提出以下建议:
$PATHS | % {Get-FolderItem -Path "$($_)" } | Select Name,DirectoryName,Length,LastWriteTime | ConvertTo-CSV -NoTypeInformation -Delimiter "|" | Out-File -FilePath $csvfile -Force -Encoding UTF8
这似乎工作正常(CSV文件正在增长,CPU似乎稳定),但当CSV文件大小达到~200MB时突然停止,控制台的错误是“管道已停止””
我不确定CSV文件的大小是否与错误消息有关,但我无法用任何一种方法处理这个大目录!关于如何成功完成此过程的任何建议?运行robocopy
列出文件并将其输出转换为PSObject数组。这是一个缓慢的操作,严格来说,实际任务并不需要它。与foreach语句相比,流水线也增加了很大的开销。在数千次或数十万次重复的情况下,这种情况变得明显
我们可以在10秒内将400000个文件的信息写入SSD驱动器,这一过程比流水线和标准PowerShell cmdlet所能提供的任何功能都要快
IO.DirectoryInfo
,以非阻塞管道方式枚举文件李>
foreach
语句,它不需要为每个项创建脚本块上下文,因此比foreach
cmdlet快得多IO.StreamWriter
以非阻塞管道方式立即写入每个文件的信息李>
List-PathsInCsv 'c:\windows', 'd:\foo\bar' 'r:\output.csv'
不要使用robocopy,请使用本机PowerShell命令,如下所示:
$PATHS = 'c:\temp', 'c:\temp2'
$csvfile='c:\temp\listresult.csv'
$PATHS | % {Get-ChildItem $_ -file -recurse } | Select Name,DirectoryName,Length,LastWriteTime | export-csv $csvfile -Delimiter '|' -Encoding UTF8 -NoType
非纯粹主义者的简短版本:
$PATHS | % {gci $_ -file -rec } | Select Name,DirectoryName,Length,LastWriteTime | epcsv $csvfile -D '|' -E UTF8 -NoT
您使用
ConvertTo Csv | Out File
而不是Export Csv
是否有特定原因?不要收集所有对象,然后进行处理。相反,你的输出就在中间。这是一项很好的工作,但它依赖于解析robocopy
输出。尝试在链接页面上使用(请参见示例:Emulate Get ChildItem以克服“路径太长”),谢谢@wOxxOm。我将尝试重构,并让您知道它是如何工作的!
$PATHS | % {gci $_ -file -rec } | Select Name,DirectoryName,Length,LastWriteTime | epcsv $csvfile -D '|' -E UTF8 -NoT