2011-01-11 13 views
2

文字列、コードなどの100万未満のファイルを検索して一致を見つけ、特定の文字列パターンのすべてのヒットをCSVファイルに出力するスクリプトを作成する必要があります。PowerShellで簡単な検索スクリプトを最適化する

これまでのところ私はこれを作った。

$location = 'C:\Work*' 

$arr = "foo", "bar" #Where "foo" and "bar" are string patterns I want to search for (separately) 

for($i=0;$i -lt $arr.length; $i++) { 
Get-ChildItem $location -recurse | select-string -pattern $($arr[$i]) | select-object Path | Export-Csv "C:\Work\Results\$($arr[$i]).txt" 
} 

これは私にそれで単語「foo」という持つすべてのファイルのリストで「foo.txtの」という名前のCSVファイル、およびすべてのファイルのリストで「bar.txt」という名前のファイルを返します。単語 "bar"を含む。

このスクリプトを最適化してより速く動作させる方法はありますか?まったく違うが、同等のスクリプトをもっと速く動かす方法についてのアイデアは?

すべての入力が高く評価されました。

+1

今はどれくらいですか(好奇心から)?出力に一致するものを含むファイルパスのみが必要ですか? –

+0

今度は配列の〜2時間のpr項目が必要です。ちょっと前に測定コマンドトリックを学びました。プロセスがキャッシュされるとパフォーマンスが向上するかどうかを確認します。 - 一致を含むファイルパスのみが必要です。はい – cc0

+0

各配列アイテム(文字列)の長さが処理時間に大きく影響するように見えることも追加できます。 CPU使用率は、最初のスルースルーの間に約15-20%でした。今それは約4-5%のようです。興味深いもの。 – cc0

答えて

2

ファイルが巨大ではありませんし、このバージョンはかなり速く動作するはずです(と私の迅速かつ汚いローカルテストがそれを証明しているようだ)メモリに読み込むことができる場合は、次の

$location = 'C:\ROM' 
$arr = "Roman", "Kuzmin" 

# remove output files 
foreach($test in $arr) { 
    Remove-Item ".\$test.txt" -ErrorAction 0 -Confirm 
} 

Get-ChildItem $location -Recurse | .{process{ if (!$_.PSIsContainer) { 
    # read all text once 
    $content = [System.IO.File]::ReadAllText($_.FullName) 
    # test patterns and output paths once 
    foreach($test in $arr) { 
     if ($content -match $test) { 
      $_.FullName >> ".\$test.txt" 
     } 
    } 
}}} 

注:1 )この例では、パスとパターンが変更されたことを気にします。 2)出力ファイルはCSVではなくプレーンテキストです。あなたがパスに興味があるならば、CSVにはそれほど理由はありません - プレーンテキストファイルは、1行に1つのパスが行います。

+0

素晴らしいです、あなたは2秒早くなりました! – stej

+0

:-)しかし私たちの提案はまったく同じではありません。したがって、@ cc0にはより多くの選択肢があり、これは良いことです。 –

+0

これは優れています:]他の人も同様にこのことから学ぶことができればと思います。時間をいただきありがとうございます! – cc0

2

1)ファイルが大きすぎず、メモリに読み込むことができます。2)実際にファイルのパスが必要で、一致する(ラインなどではない)としましょう。

ファイルを一度だけ読み込み、その後正規表現を反復しようとしました。最終的な結果はファイルサイズ、ファイル数などの他の要因に依存します。

また、'ignorecase'を削除すると、少し速くなります。

$res = @{} 
$arr | % { $res[$_] = @() } 

Get-ChildItem $location -recurse | 
    ? { !$_.PsIsContainer } | 
    % { $file = $_ 
     $text = [Io.File]::ReadAllText($file.FullName) 
     $arr | 
     % { $regex = $_ 
      if ([Regex]::IsMatch($text, $regex, 'ignorecase')) { 
       $res[$regex] = $file.FullName 
      } 
     } 
    } 
$res.GetEnumerator() | % { 
    $_.Value | Export-Csv "d:\temp\so-res$($_.Key).txt" 
} 
+0

ありがとうございます:)私はこれもショットを与え、私の状況の方が速いのを見ていきます。面白いはずです! – cc0

+0

あなたの編集した質問に結果が表示されるのはすばらしいことです) – stej

+0

私はそれらを持っているとすぐにそれを行います:] 2,3日かかるかもしれません。 – cc0

関連する問題