Linuxanfängerfrage: Wie geht "grep"?

Ich suche alle Dateien, die ein Wort enthalten.
Beispiel.
Vor 3 Monaten (oder 5 Wochen) schrieb ich etwas über Tiere. Die Datei heisst irgendwas mit tier am Anfang und das Wort hase ist darin.
Nun Tutorial sagt:
grep -n ‚halo‘ datei.txt
und ich gebe ein:
grep -r ‚hase‘ tier*.txt >ergebnis.txt,
aber es kommt nur Fehlermeldung:
Datei oder Verzeichnis nicht gefunden.
Linux soll HD ganz durchsuchen.

Was mache ich bitte falsch?

Geschaut habe ich auf:

https://kushellig.de/linux-unix-grep-befehl-beispiele/

Hallo,

tier*.txt wird ab dem aktuellen Verzeichnis durchsucht. Du willst vermutlich:

$ find / -type f | xargs grep -r 'hase'

Ich würde ja zumindest noch dazu schreiben, was da passiert.

Das Problem ist folgendes:

grep -r 'hase' * schaut sich alles im aktuellen Verzeichnis an. Findet es Dateien, durchsucht es sie nach „hase“. Findet es Ordner, geht es wegen -r dort ein, und sucht auch darin.

grep -r 'hase' tier*.txt schaut sich alles im aktuellen Verzeichnis an, was dem Muster tier*.txt entspricht, und lässt alles andere links liegen. Solange ein Unterordner nicht auch zufällig tierGiraffe.txt heißt, wird der auch nicht beachtet. Deshalb findet grep nichts.

Deine Lösung besteht aus zwei Schritten:

find / -type f listet ab dem Wurzelverzeichnis (/) rekursiv alles auf, was ne Datei ist (-type f)
Diese Liste wird an xargs übergeben, welches für jede Datei in der Liste den Befehl
grep -r 'hase' {Datei} aufruft.

Dazu zwei Anmerkungen:

  1. find / -type f findet ALLE Dateien, egal, ob Bilder, Binärdateien oder Textdateien. Die dann alle von grep durchsuchen zu lassen, dauert Jahre, und liefert viele falsche Treffer.
    Mit find / -type f -iname 'tier*.txt' werden nur die Dateien gefunden, die dem Muster entsprechen.
  2. Das -r wird für grep nicht mehr benötigt, da es ja die Dateinamen einzeln bekommt. Funktionell wird das keinen Unterschied machen, aber möglicherweise macht es die Sache langsamer.

heißt also:

find / -type f -iname 'tier*.txt' | xargs grep 'hase'

(Nebenbei wird so auch z.B. /usr durchsucht. Das Verzeichnis ist riesig, das Durchsuchen dauert also lange. Und da sind garantiert keine Dokumente drin. ggf sucht man statt in / zunächst besser in ~. )

3 Like

Du hast natürlich recht, ich bin lediglich der Forderung nachgekommen, daß die „HD ganz durchsucht“ wird.

Für die Praxis noch der Tip:

$ find / -type f -iname 'tier*.txt' -print0 | xargs -0 grep 'hase'

dann gehen auch Dateien mit Leerzeichen, Zeilenumbrüchen und Co.

Kurze Nachfragen:
a Ganz HD oder ganzen Stick durchsuchen:
Find und nicht grep?
PK.
Danke.

b Heisst -r nicht: Durchsuche alle Unterverzeichnisse, habe ich das falsch verstanden.

c Suche also mit find … > ergebnis.txt, das geht doch?

Danke an alle.
Wird ausgedruckt.

d Kann ich in Linux auch Datei tier*.txt suchen/finden wenn alle Textdateien in einer ZIP Datei gepackt wurden?

e grep nur dann, wenn ich Ordner kenne, wo tier*.txt drin ist?

Danke an alle.
Wird ausgedruckt.

Hallo!

Ja. Wie gesagt, der Filter tier*.txt in grep behandelt nur Dateien und Ordner, die auf dieses Muster passen. Demnach werden Ordner, die nicht z.B. tierGiraffe.txtheißen, komplett ignoriert, und auch nicht weiter durchsucht. find arbeitet da anders.

Doch, das hast du richtig verstanden. Aber wie gesagt, dieser Filter wird auch auf den Ordnernamen angewandt. Ist ziemlich bescheiden, wenn du mich fragst.

Ja,

find / -type f -iname 'tier*.txt' -print0 | xargs -0 grep 'hase' > ergebnis.txt

funktioniert.

Es ist nicht so einfach möglich, eine zip-Datei wie einen Ordner zu behandeln, wenn du das meinst.

Man kann auf der Kommandoszeile mit unzip -l MeineZipdatei.zip ausgeben, welche Dateien überhaupt drin sind, das nach dem Muster durchsuchen, und nur, wenn dieses Muster auch drin ist, entpacken und durchsuchen. Wenn jedes ZIP entpacket wird, dauert es wieder ewig.

Nein, sondern nur dann, wenn der Filter mehr als nur * ist.

Geht mit bsdtar, ist aber eine separate find-Zeile:

$ find / -type f -iname '*.zip' -exec bsdtar xf '{}' -O 'tier*.txt' | grep hase

grep nimmt an sich nur Dateien, -r ist eine Erweiterung von GNU grep, wozu auch immer. Meine Shell ist zsh, deshalb mache ich solche find-Arien einfach mit Globbing:

$ grep 'hase' **/tier*.txt

(geht nur in zsh).

find / -type f -iname ‚tier*.txt‘ | xargs grep ‚hase‘
klappt prima, danke.

und ein Extra-Sternchen für die Verwendung von xargs anstelle von find -exec $COMMAND {} ;

Lesetipp: man xargs.

Sebastian