Effizientester Befehl zum Durchsuchen der ersten Zeile vieler Dateien (Windows)

Effizientester Befehl zum Durchsuchen der ersten Zeile vieler Dateien (Windows)

Ich bin neu im Windows-Ökosystem. Ich habe die Aufgabe, ein Programm zu schreiben, das mehrere Zehntausend (vielleicht sogar Hunderttausende) von Dateien nach einer bestimmten Zeichenfolge durchsucht. Die Zeichenfolge, die übereinstimmen muss, ist eine Seriennummer, die nur aus Zahlen und Buchstaben besteht und weniger als 20 Zeichen lang ist. Im Moment führt mein Programm den folgenden Befehl aus:

findstr /i /m /s "searchStr" "C:\Directory\To\Search\*.*"

Der obige Befehl funktioniert, ist jedoch zu langsam. Die Dateien, die eine bestimmte Seriennummer enthalten könnten, haben diese Seriennummer nur in der ersten Zeile.

Kennt jemand eine effiziente Möglichkeit, ein Verzeichnis rekursiv nach allen Dateien zu durchsuchen, die eine bestimmte Zeichenfolge nur in der ersten Zeile enthalten?

Antwort1

In PowerShell (v3.0+) vielleicht ...

Get-ChildItem -Path x:\pathto\*.log `
| ForEach-Object {
    if (Get-Content -LiteralPath $_ -First 1 `
        | Select-String -SimpleMatch -Pattern 'serialnumber') 
    {
        Write-Output $_
    }
}

Verschiedene Parameter Get-ChildItemermöglichen die Rekursion in Unterordnern usw., das Get-ContentAbrufen von mehr oder weniger Inhalt aus der Datei und das Select-StringDurchführen komplexerer Übereinstimmungen (reguläre Ausdrücke, Groß-/Kleinschreibung usw.).

Antwort2

Ich kann Ihnen ein paar Optionen vorschlagen, wenn Sie nicht verwenden müssen findstr, aber zunächst sollten Sie prüfen, ob Sie die Suche auf Dateien eines bestimmten Dateityps beschränken können, da dies die Sache sicherlich beschleunigen würde.

  1. FileLocator Liteist meiner Erfahrung nach schneller beim Auffinden von Dateien und Überprüfen ihres Inhalts. Achten Sie darauf, sowohl die Felder „Dateiname“ (falls zutreffend) und „enthaltener Text“ als auch das Startverzeichnis auszufüllen.

  2. ag -il "searchStr":agist auf Geschwindigkeit ausgelegt und sollte Ihnen daher schnell Ergebnisse liefern. Achten Sie darauf, die Suche nach Dateityp einzuschränken, wenn Sie können, obwohl Binärdateien bereits standardmäßig übersprungen werden. Auch verfügbar unterCygwin.

  3. find -exec awk 'BEGIN {IGNORECASE=1} NR==1 && /searchStr/ {print FILENAME": "$0}' {} \;Versuchen Sie dies, wenn Sie Cygwin oder eine andere POSIX-ähnliche Umgebung zur Verfügung haben, um Ihre Idee zu testen, nur die erste Zeile zu durchsuchen. Kombinieren Sie dies, findum die Dateinamen abzurufen (und sie hoffentlich auch zu filtern) und awkum die erste Zeile zu prüfen und sie zusammen mit dem Dateinamen auszudrucken.
  4. find | parallel 'perl -lane '\'' print "$ARGV: $_" if $. == 1 and /searchStr/i '\'' {}'Eine weitere Idee, die Dinge zu beschleunigen, besteht darin, verfügbare Kerne und Threads zu nutzen: Das ist es, wasGNU parallelist für. Dieses Beispiel enthält perl, macht aber dasselbe wie awkoben 3.. Hier ist eine Befehlsaufschlüsselung:

    findSuchen Sie im aktuellen Verzeichnis und seinen Unterverzeichnissen nach Dateien. Sie können ein anderes Verzeichnis angeben, in dem gesucht werden soll, und ein Dateimuster oder eine Erweiterung, nach der gefiltert werden soll: find /cygdrive/c/Directory/To/Search -iname "*.txt".

    |„Pipe“, d. h. die Ergebnisliste an den nächsten Befehl weiterleiten.

    parallelFühren Sie den nächsten Befehl parallel aus.

    perlSkriptsprache, die sich hervorragend zur Textdateibearbeitung eignet und ersetzen kann sedoder awk.

    -lanenützlicher Satz von Schaltern für Perl-Einzeiler.

    '\''Escape-Apostroph, erforderlich, da wir nach bereits einen Apostrophsatz geöffnet haben parallel.

    print "$ARGV: $_"Drucken Sie den Dateinamen ( $ARGV), einen Doppelpunkt, ein Leerzeichen und die vollständige Zeile ( $_).

    ifFühren Sie die vorherige Anweisung nur aus, wenn die folgende(n) Bedingung(en) erfüllt sind.

    $. == 1Zeilennummer ( $.) ist gleich eins ( 1), d. h. wir betrachten die erste Zeile der Datei.

    andAußerdem muss folgende Bedingung erfüllt sein.

    /searchStr/idie untersuchte Zeile enthält den Text searchStr, ohne Berücksichtigung der Groß-/Kleinschreibung.

    '\''Ein weiteres maskiertes Apostroph markiert das Ende der perlAnweisung.

    {}Dies wird durch parallelden jeweils von übergebenen Dateinamen ersetzt find.

    'Ende der parallelAnleitung.

Aktualisieren:Beides awkund perllesen Sie die gesamte Datei, auch wenn Aktionen nur an die erste Zeile gebunden sind. Die Lösung besteht darin, die Ausarbeitung explizit in Zeile 2 zu beenden:

find -exec awk 'BEGIN {IGNORECASE=1} NR > 1 {exit} /searchStr/ {print FILENAME": "$0}' {} \; find | parallel 'perl -lape '\'' exit if $. == 2; print "$ARGV: $_" if /searchStr/i '\'' {}'

verwandte Informationen