如何使用Powershell管道来避免大型对象?

如何使用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 "|" 这

我使用一个自定义函数在8TB驱动器(数千个文件)上执行DIR命令(递归文件列表)

我的第一次迭代是:

$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所能提供的任何功能都要快

  • .NET Framework 4或更新版本(从Win8开始提供,可在Win7/XP上安装)
    IO.DirectoryInfo
    ,以非阻塞管道方式枚举文件
  • PowerShell 3或更高版本,因为它总体上比PS2快
  • foreach
    语句,它不需要为每个项创建脚本块上下文,因此比
    foreach
    cmdlet快得多
  • IO.StreamWriter
    以非阻塞管道方式立即写入每个文件的信息
  • 取消260个字符的路径长度限制
  • 手动对要处理的目录进行排队,以通过“拒绝访问”错误,否则将停止naive IO.DirectoryInfo枚举
  • 进度报告
  • 用法:

    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