Wie greife ich die ersten 50 Zeilen jeder Datei in einem Verzeichnis rekursiv ab?

9

Ich muss die ersten 50 Zeilen jeder Datei in einem Verzeichnis und seinen Unterverzeichnissen durchsuchen.

Dies erledigt den rekursiven Teil, aber wie beschränke ich mich auf die ersten 50 Zeilen jeder Datei?

grep -r "matching string here" .

Einige dieser Dateien sind riesig und ich möchte nur, dass sie in den ersten 50 Zeilen übereinstimmen. Ich versuche, den Prozess zu beschleunigen, indem ich in einigen Dateien keine Megabyte an Binärdaten durchsuche.

Zevlag
quelle
Möchten Sie nur die übereinstimmenden Dateien kennen oder möchten Sie nur die passende Zeichenfolge haben oder möchten Sie die übereinstimmende Zeichenfolge zusammen mit dem Dateinamen?
gniourf_gniourf

Antworten:

11
  • Wenn Sie nur die passenden Dateien möchten:

    find . -type f -exec bash -c 'grep -q "matching string here" < <(head -n 50 "$1")' _ {} \; -printf '%p\n'
    

    oder

    find . -type f -exec bash -c 'grep -q "matching string here" < <(head -n 50 "$1") && printf '%s\n' "$1"' _ {} \;
    
  • Wenn Sie nur die passenden Zeichenfolgen möchten:

    find . -type f -exec head -n 50 {} \; | grep "matching string here"
    

    oder besser,

    find . -type f -exec head -q -n 50 {} + | grep "matching string here"
    
  • Und wenn Sie beides wollen:

    find . -type f -exec bash -c 'mapfile -t a < <(head -n 50 "$1" | grep "matching string here"); printf "$1: %s\n" "${a[@]}"' _ {} \;
    

Bemerkungen.

  • Könnte etwas einfacher sein als mit sedder Combo head- grep.
  • Lassen Sie mich betonen, dass alle drei Methoden in Bezug auf Dateinamen, die möglicherweise lustige Symbole (Leerzeichen, Zeilenumbrüche usw.) enthalten, 100% sicher sind.
  • Bei zwei dieser Methoden gehe ich davon aus, dass Sie eine anständige aktuelle Version von Bash haben.
  • Sie könnten -exec ... +in jeder Methode verwenden, aber dann müssen Sie Ihre innere Schleife selbst codieren! (triviale Übung dem Leser überlassen). Dies ist möglicherweise etwas effizienter, wenn Sie über eine Unmenge von Dateien verfügen.
gniourf_gniourf
quelle
4

Wenn Sie die grep-Ausgabe wie im Original benötigen, können Sie Folgendes tun:

find . -type f | while read f; do 
  if head -n 50 "$f"|grep -s "matching string here"; then
    grep "matching string here" "$f" /dev/null 
  fi
done

Wenn Sie nur die Dateinamen benötigen, können Sie den 2. grep durch ersetzen echo "$f".

Michael Suelmann
quelle
1

Sie müssen einige verschiedene Dienstprogramme kombinieren, um die gewünschte Funktionalität zu erhalten. Verwenden Sie den findBefehl, um die Verzeichnisse zu rekursieren, alle Dateien zu suchen und den headBefehl für jede gefundene Datei auszuführen . Mit dem headBefehl können nur die ersten 50 Zeilen jeder Datei ausgegeben werden. Zuletzt leiten Sie die Ausgabe an grep weiter, um nach der gewünschten Zeichenfolge zu suchen.

find . -type f -exec head -n 50 {} ";" | grep "matching string here"

Hundehaare
quelle