Frage

Ich brauche ein Skript zu erstellen, unter einer Million Dateien von Text durchsuchen nur, Code usw. Übereinstimmungen zu finden und dann ausgegeben alle Zugriffe auf einem bestimmten Zeichenfolge Muster in eine CSV-Datei.

Bisher habe ich diese;

$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"
}

Das gibt mir eine CSV-Datei „foo.txt“ mit einer Liste aller Dateien mit dem Wort „foo“ in ihm benannt, und eine Datei mit dem Namen „bar.txt“ mit einer Liste aller Dateien, die das Wort " bar“.

Gibt es eine Möglichkeit jemand denken kann, dieses Skript zu optimieren, um es schneller zu arbeiten? Oder Ideen, wie einen ganz anderes zu machen, aber gleichwertigen Skript, das funktioniert einfach schneller?

Alle Eingaben zu schätzen!

War es hilfreich?

Lösung

Wenn Sie Ihre Dateien nicht sehr groß sind und in dem Speicher gelesen werden, dann ist diese Version sollte recht schneller arbeiten (und mein schneller und unsauberer Test, scheint zu beweisen):

$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"
        }
    }
}}}

Anmerkungen: 1) Meinung geändert Pfade und Muster im Beispiel; 2) Ausgabedateien sind nicht CSV sondern Klartext; es gibt nicht viel Grund in CSV ist, wenn Sie nur in Pfade interessiert sind -. Klartext-Dateien einen Pfad pro Zeile tun

Andere Tipps

Nehmen wir an, dass 1) die Dateien nicht zu groß und man kann es in den Speicher laden, 2) Sie wirklich wollen nur den Pfad der Datei, dass Streichhölzer (nicht die Linie usw.).

Ich habe versucht, die Datei nur einmal und dann eine Iteration durch die reguläre Ausdrücke zu lesen. Es besteht eine gewisse Verstärkung (es ist ein schneller als die ursprüngliche Lösung), aber das Endergebnis wird von anderen Faktoren wie Dateigrößen abhängig sind, zählen von Dateien etc.

Auch das Entfernen 'ignorecase' macht es schneller, ein wenig.

$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"
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top