2014-03-06 20 views
1

问候光荣同志CSV,Powershell的行数与大量文本文件

我再次需要借用你的才华最大化我的解决方案能力。

我必须使用powershell遍历大量文本文件(某些情况下为20 GB)的目录,提取文件名,行计数和创建日期,然后将该信息输出到csv中。

这是到目前为止我的代码:

$fileEntries = [IO.Directory]::GetFiles("T:\frg\working"); 
foreach($fileName in $fileEntries) 
{ 
    $count = 0 
    $filedate = (Get-Date).Date 
    $reader = New-Object IO.StreamReader $filename 
    while($reader.ReadLine() -ne $null){$count++} 
    $reader.close() 
    #Get-Content $filename | %{$lines++} 
    [Console]::Writeline($filename+" "+$count+" "+ $filedate); 

} 

一开始日期只是一个临时填料,直到我能得到的文件创建日期。

目前,它输出类似于:

T:\frg\working\file1.txt 90055 03/06/2014 00:00:00 
T:\frg\working\file2.txt 6419616 03/06/2014 00:00:00 

但对我的生活我不能管这个成功CSV文件。

我试着设置一个自定义属性的对象并输出到该对象,但它说管道是空的。

巨大的文件大小阻止使用Import-csv选项(将20GB导入内存导致一些问题)。如果我可以通过扩展过滤,它也会很整洁,但如果不能,我可以解决它。

任何指针将不胜感激,谢谢你提前。

回答

3

试试这个:

$fileEntries = [IO.Directory]::GetFiles("T:\frg\working") 

$RecordCounts = 
    foreach($fileName in $fileEntries) 
    { 
    $count = 0 
    $filedate = (Get-Date).Date 
    Get-Content $fileName -ReadCount 1000 | 
    foreach {$count += $_.count} 

    New-Object psobject -Property @{FileName = $fileName;Count = $count;FileDate = $filedate} 
} 

$RecordCounts | Export-Csv c:\somedir\RecordCounts.csv 

编辑: 测试3个靠在小的1GB的文件解决方案,超过12万线:

$testfile = 'c:\testfiles\bigfile.txt' 

'Get-Content | Measure-Object' 
(measure-command { 
Get-Content $testfile | 
    Measure-Object -Line | select -expand Lines 
}).TotalSeconds 
'' 

'StreamReader' 
(measure-command { 
$count=0 
$reader = New-Object IO.StreamReader $testfile 
while($reader.ReadLine() -ne $null){$count++} 
$reader.close() 
}).TotalSeconds 
'' 

'Get-Content -ReadCount' 
(measure-command { 
$count=0 
Get-Content $testfile -ReadCount 1000 | 
    foreach {$count += $_.count} 
}).TotalSeconds 



Get-Content | Measure-Object 
175.0600678 

StreamReader 
20.3832785 

Get-Content -ReadCount 
6.0199737 
+0

由于答案的彻底性,标记为答案,但是所有这些提交都有效。 –

1

这几乎是你所有的代码在这里...我添加$Output作为ForEach循环外的空数组。然后在循环内部,我使用您指定的值创建一个自定义对象,并将该对象添加到数组中以进行每次传递。最后,我在ForEach循环的最后使用Export-CSV将$Output保存为CSV文件。

$fileEntries = [IO.Directory]::GetFiles("T:\frg\working"); 
$OutPut = @() 
foreach($fileName in $fileEntries) 
{ 
    $count = 0 
    $filedate = (Get-Date).Date 
    $reader = New-Object IO.StreamReader $filename 
    while($reader.ReadLine() -ne $null){$count++} 
    $reader.close() 
    #Get-Content $filename | %{$lines++} 
    [Console]::Writeline($filename+" "+$count+" "+ $filedate); 
    $Current = New-Object -TypeName PSObject -Property @{ 
     FileName = $filename 
     Count = $count 
     FileDate = $filedate 
    } 
    $Output += $Current 
} 
$Output|Export-CSV C:\SomeFile.csv -notypeinfo 
+0

确认此操作。仍在测试其他答案。 –

+0

我只是“修复”你的代码来做你想做的事情。说实话,如果我是你,我会用mjolinor的答案。在我看来,他就像Powershell的Merlin ......他的剧本通常类似于魔术。 – TheMadTechnician

2

这是我会怎么做它:

gci *.txt | % { 
    $lineCount = gc $_ | Measure-Object -Line | select -expand Lines 
    select -InputObject $_ CreationTime, Name, @{Name="LineCount"; Expression={$lineCount}} 
    } | ConvertTo-Csv 

从我的测试中,文件上的gc似乎不会将整个文件加载到内存中(它必须使用一些流水线魔术),因此可能不需要编写自己的行计数器。

我在PS3中测试过。其中一个文本文件是13GB。

+0

那么我要在循环中添加它吗?我不确定在这里添加路径目标的位置。 –

+0

你可以用'gci T:\ frg \ working \ *。txt'替换脚本中的'gci * .txt'。这将获得该目录中的所有.txt文件。('gci'是'Get-ChildItem'的缩写;如果你熟悉'''''''''',那么它与旧cmd.exe中'dir'类似。)你是什么意思?“如果可以的话,它也会很整洁通过扩展过滤“? –

+0

我需要评估的某些文件具有像GUID那样的文件扩展名。所以做一些像<> * .txt可能很有价值。 –