2014-03-06 21 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可能很有價值。 –