• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

[Gelöst] grep arbeitet nicht rekursiv

Zeneca

Newbie
Hallo allerseits,

hab mir jetzt endlich mal wieder ein Linux installiert und wollte ganz standard-mäßig mit:

Code:
grep -n -r text *.cpp
nach "text" suchen aber es werden alle Unterverzeichnisse ignoriert
es ist ein GNU grep 3.3 installiert. (lt. apt-get aktuelle Version)

probiert habe ich natürlich noch:
grep -R oder -d recursive
den text mit und ohne Anführungsstriche, Hochkommata oder Wildcards (*)
und vieles mehr
habe nun keine Idee was ich noch versuchen könnte
und das Kommando ist wirklich essentiell für mich.
Wäre schön, wenn ich noch ein paar Anregungen bekäme woran es noch liegen könnte

besten Dank im Voraus

Zen
 

marce

Guru
Aus dem Kopf heraus: wenn in ./ keine *.cpp-Files liegen (also dort nichts matcht) geht grep auch nicht in die Tiefe.

Es gibt bestimmt eine coole direkte Lösung, ich würde aber einfach
Code:
find . -type f -name "*.cpp" -exec grep $pattern {} ';'
versuchen, da mir die direkte coole Lösung so direkt gerade nicht einfällt.
 
OP
Z

Zeneca

Newbie
marce schrieb:
Aus dem Kopf heraus: wenn in ./ keine *.cpp-Files liegen (also dort nichts macht) geht grep auch nicht in die Tiefe.

das wäre ja doof, aber gibt auch entsprechende Dateitypen im Wurzelverzeichnis
habe auch gerade noch mal versucht nach einem Text zu suchen der sowohl im Wurzelverzeichnis als auch
in den Unterverzeichnissen vorkommt, da werden wieder nur die Treffer aus dem Wurzelverzeichnis angezeigt

marce schrieb:
Es gibt bestimmt eine coole direkte Lösung, ich würde aber einfach
Code:
find . -type f -name "*.cpp" -exec grep $pattern {} ';'
versuchen, da mir die direkte coole Lösung so direkt gerade nicht einfällt.

ja, die Lösung hab ich bei meiner Recherche auch gefunden,
finde ich aber extrem unpraktikabel :(
trotzdem vielen Dank erst mal
wäre aber schön, wenn sich das noch irgendwie klären könnte

Lieber Gruß
Zen
 

abgdf

Guru
Kannst Dir ja ein Skript "greprecursive" drumrumbauen, und das (als root) nach "/usr/local/bin" kopieren:
Code:
#!/bin/bash

# greprecursive

if test -z "$2"; then
    echo "Error: Two arguments needed."
    exit 1
fi

find . -type f -name "$1" -exec grep "$2" {} ';'
 
OP
Z

Zeneca

Newbie
das ist ja herzallerliebst :)
würde ich aber eher so lösen:
Code:
alias grp='f(){ find . -type f -name "*.cpp" -exec grep "$@" {} \;;  unset -f f; }; f'

...und um es rund zu machen

Code:
alias grp='f(){ find . -type f -name "*.cpp" -exec grep --colour -H -n "$@" {} \;;  unset -f f; }; f'

...aber das ist doch alles Schnick-Schnack, warum funzt das nicht wie ich es gewohnt bin??
 
A

Anonymous

Gast
Zeneca schrieb:
Code:
grep -n -r text *.cpp
Warum funktioniert das nicht wie du es dir vorstellst?
ich denke mal da ist ein Kleiner Denkfehler von dir. Ich gehe davon aus, du willst rekursive mit grep nach "text" suchen aber nur in cpp-Dateien.

So wie du den grep-Befehl geschrieben hast, wird aber "text" in allen Dateien unterhalb von Verzeichnissen "*.cpp" gesucht. Schon so ähnlich wie es marce schon vermutet hat, nur noch schlimmer, er würde nicht mal in eine cpp-Datei im aktuellen Verzeichnis reinschauen, sondern nur wenn Verzeichnisse am ende des Namens ".cpp" haben würde, würde er diese rekursiv durchsuchen, aber dort alle Dateien die er finden kann. Also was ganz anderes, als das, was du machen wolltest.

Beim rekursiv suchen wird von grep der Dateinamen als reiner Verzeichnisname interpretiert. Wenn man jetzt aber nur in spezielle Dateinamen/type rekursiv suchen will, und nicht alle Dateien, dann muss man auch nicht unbedingt sich noch mit find und -exec rumschlagen. Mit grep lassen sich Datei/Verzeichnisnamen gezielt ausschließen oder auswählen.
Also: Verzeichnis weglassen oder auch * , dann wird automatisch vom aktuellen Verzeichnis aus gesucht.
-r oder -R , der Unterschied liegt in der Behandlung von Links, und mit --include kannst du dann mit Wildcards explizite Dateinamen aussuchen, in denen er nur suchen soll.

Code:
grep -n -r text --include=*.cpp
(geht eventuell auch ohne "=") macht dann genau das was du wohl beabsichtigt hast, ohne erst noch riesige Befehlzeilen mit find zu erfinden.

robi
 

marce

Guru
Fast: :)
Code:
[marc@md-to01 tmp]$ grep -r test *
a.html:test
a.test:test
b/a.html:test
c/a.html:test
d.html/a.html:test
d.html/a.test:test
z.html:test
[marc@md-to01 tmp]$ grep -r test *.html
a.html:test
d.html/a.html:test
d.html/a.test:test
z.html:test
[marc@md-to01 tmp]$ grep -r test --include=*.html *
a.html:test
b/a.html:test
c/a.html:test
d.html/a.html:test
z.html:test
[marc@md-to01 tmp]$ grep -r test --include=*.html *.html
a.html:test
d.html/a.html:test
z.html:test
[marc@md-to01 tmp]$ grep -r test --include=*.test *.html
d.html/a.test:test

Sprich: grep -r $pattern $file geht auf alle Files und Directories, die auf $file matchen rekursiv los. Welche Files er darin dann anschaut kann man ggf. noch mit --include spezifizieren. Ich hoffe, das trifft's so einigermaßen und ist nicht zu sehr vereinfacht...
 

drcux

Hacker
$file wird von der Bash "aufgelöst", nicht von grep!

aus

grep blah *.txt

wird

grep blah a.txt b.txt c.txt

wenn die drei Dateien im aktuellen Verzeichnis sind. Deswegen auch bei dem find-Befehl die Anführungszeichen um den Suchbegriff, sonst würde es dort auch passieren.
 

gehrke

Administrator
Teammitglied
robi schrieb:
Beim rekursiv suchen wird von grep der Dateinamen als reiner Verzeichnisname interpretiert.

@robi: Du zerstörst mit solchen Posts noch meine wohlgepflegtesten Bildungslücken.
TNX
 
OP
Z

Zeneca

Newbie
Hallo noch mal,

also, vorab, mit --include= geht's :) (das = ist wohl erforderlich)
aber, wie auch marce in seinen Tests zeigt, funktioniert es sehr wohl im Wurzelverzeichnis ohne include
sonst hätte ich vielleicht auch noch mal anders darüber nachgedacht
auch war es bescheuert von mir es nicht einmal ohne den Extension-Parameter zu probieren
da wäre mir auch aufgefallen, daß es damit wohl zusammenhängt,
ob ich deshalb auf die Lösung gekommen wäre weiß ich auch nicht
aber im man(ual) reden die eigentlich auch nur von Datei:

"grep sucht in jeder DATEI nach MUSTERN. MUSTER ist ein oder mehrere Muster,
die durch Zeilenumbrüche getrennt sind und grep gibt jede Zeile aus, die auf ein Musster passt.
Ist DATEI »-« bedeutet dies Standardeingabe. Falls keine DATEI angegeben ist, werden rekursive Suchen
das aktuelle Verzeichnis prüfen und nichtrekursive Suchen die Standardeingabe lesen."

ich weiß auch nicht wie man darauf kommen kann, denn bei der -r Option
steht nur dabei, wenn kein Datei-Operand angegeben ist würde er nur das Arbeitsverzeichnis durchsuchen

einen kleinen Hinweis bekommt man vielleicht dadurch, wenn man einen Typ angibt der nicht im Wurzelverzeichnis
(aber im Unterverzeichnis) vorhanden ist,
da kommt dann die Fehlermeldung: Datei oder Verzeichnis nicht gefunden

im grep das ich mir seinerzeit für Windows gezogen hatte hat er sich nicht so angestellt ;-)
...und wenn ich mich recht zurück erinnere war es beim Cygwin auch nicht so kompliziert

und klar ging es mir darum das Gemurkse mit dem find zu vermeiden,
deshalb bin ich ja auch dran geblieben und bin froh, daß sich das jetzt geklärt hat

also: vielen Dank für die Lösung und alle die sich darum bemüht haben *wink

Zen
 
Oben