Dateien mit bestimmten Inhalt auflisten

Post Reply
Message
Author
micbur
Posts: 86
Joined: 05. Jun 2004 15:55

Dateien mit bestimmten Inhalt auflisten

#1 Post by micbur »

Hallo,

ich probiere hier schon seit Stunden mit find rum.
Ich möchte mir gerne eine Liste von Dateien (absoluter Pfad) anzeigen lassen, die einen bestimmten Inhalt haben.

Momentan suche ich alle *.htm* Dateien, mit dem Suchkriterium '<!--MDV'.

Kann mir da bitte jemand weiter helfen. Ich bekomme das einfach nicht hin.
In Stichproben sind auch Dateien dabei gewesen, die nicht <!--MDV enthielten und die Pfadangabe ist auch noch nicht absolut.

Wäre echt schön, wenn mir jemand einen kleinen Hinweis geben könnte.
Vielen Dank, micbur

User avatar
Lateralus
prolinux-forum-admin
Posts: 1238
Joined: 05. May 2004 7:35

#2 Post by Lateralus »

Code: Select all

find . -name *.htm -exec grep -l '<!--MDV' &#123;&#125; \; | awk "&#123; sub&#40;\".\", \"$PWD\"&#41;; print &#125;"
durchsucht den aktuellen Pfad rekursiv und zeigt die Dateinamen, welche auf ".htm" enden an, welche die Zeichenkette enthalten. Das kleine awk-Skript dahinter, ersetzt den ersten Punkt im Dateinamen durch den aktuellen Pfad.

edit: Ich dachte eigentlich, dass find eine Option hätte, den vollen Pfad anzuzeigen, dann würde sich das awk-Skript erledigen, habe aber leider nichts gefunden.

kanonenfutter
Posts: 266
Joined: 10. Sep 2004 14:37
Contact:

#3 Post by kanonenfutter »

oder halt einfach

Code: Select all

grep -rl "<!--MDV" *.htm
"Email und Internet haben gemeinsam, dass sie beide in HTML geschrieben sind" (Peter Huth, TV-Computerexperte). Zitiert nach http://www.antihuth.de/

micbur
Posts: 86
Joined: 05. Jun 2004 15:55

#4 Post by micbur »

Hallo,

vielen Dank.
Ich hatte auch ins Manual von find geschaut und habe dann mit der Option 'printf' rumgespielt.

Vielleicht interessiert euch meine Ausgabe:

Code: Select all

&#91;user@host /dir&#93;# find . -name *.htm -exec grep -rl "\<!--MDV" *.htm
-bash&#58; !--MDV"&#58; event not found
letztlich habe ich es mit der langen Befehlsfolge probiert. Das hat auch funktioniert.

Code: Select all

find . -name *.htm -exec grep -l 'MDV' &#123;&#125; \; | awk "&#123; sub&#40;\".\", \"$PWD\"&#41;; print &#125;"

User avatar
jochen
prolinux-forum-admin
Posts: 699
Joined: 14. Jan 2000 15:37
Location: Jülich
Contact:

#5 Post by jochen »

Hi allerseits!

Fehlermeldung:
-bash: !--MDV": event not found
Das "!" ist das Zeichen für die History Expansion (unter dieser Überschrift in der bash-Manpage zu finden). So wird z.B. !$ als "letztes Wort des letzten Kommandos" ausgewertet:

Code: Select all

mkdir -p /ein/ganz/tief/geschachteltes/verzeichnis
cd !$
Mit dem cd-Kommando wird in das gerade frisch erstellte Verzeichnis gewechselt. Wenn man diese History Expansion nicht braucht/möchte, hat man 2 Möglichkeiten. Man entwertet das ! mittels vorgestelltem Backslash (\!) oder mittels Apostrophen ('!') oder man schaltet mittels "set +H" die History Expansion ganz aus. Die Fehlermeldung kannst Du also beispielsweise so umgehen:

Code: Select all

find . -name *.htm -exec grep -l '<!--MDV' *.htm 
In einem Skript würde die Fehlermeldung sowieso nicht auftauchen, da nicht interaktive Shells die History Expansion per Default ausgeschaltet haben.

Absoluter Pfad bei find:
Wenn man von find eine volle Pfadangabe haben möchte, muss man ihm auch sagen, dass man eine möchte. Nur geht das nicht über eine Option, sondern über die Art, wie man find sagt ab welchen Verzeichnissen er zu arbeiten hat. Schreibt man

Code: Select all

cd /tmp
find . -type f -print
dann erhält man relative Pfadnamen, da das erste Argument zu find, also das Verzeichnis, ab dem find arbeiten soll, relativ angegeben wurde. Schreibt man statt dessen

Code: Select all

find /tmp -type f -print
so gibt find auch absolute Pfadnamen aus. Möchte man nun "ab dem aktuellen Verzeichnis absolute Pfadnamen" erreichen, geht das auch:

Code: Select all

find $PWD -type f -print
find `pwd` -type f -print
Die erste Variante funktioniert in der bash oder ksh, die zweite auch in der alten sh.

Tuning:
Bei "find .... -exec ... \;" ist mir immer ein bisschen unwohl. Wenn man Verzeichnisbäume rekursiv durchsucht, muss man mit vielen Treffern rechnen. Und für jeden einzelnen Treffer wird wiederum ein eigenes grep-Kommando gestartet - möglicherweise bei 1000 Dateien also 1000 Prozesse. Mittels "xargs" kann man das viel effektiver gestalten:

Code: Select all

find $PWD -name "*.htm" -print0 | xargs -0r grep -l '<!--MDV'
find liefert wie o.a. die gewünschten Dateien und gibt deren Namen in die Pipeline aus. Zwischen die Namen werden Nullbytes als Trenner gesetzt (-print0). xargs erwartet das auch so, weil wir die Option -O gesetzt haben. Er nimmt die Liste von Dateien und setzt sie als Argumentliste für das grep-Kommando zusammen. Sollte allerdings find keinen einzigen Treffer liefern, wird grep nicht gestartet (-r). Beispiel: Wenn find die Dateien

1.htm
2.htm
3.htm

liefert, setzt xargs daraus das Kommando

Code: Select all

grep -l '<!--MDV' 1.htm 2.htm 3.htm
zusammen und startet es. Egal wieviele Treffer find liefert, es werden immer genau 3 Prozesse gestartet: find, xargs, grep. (Ja, ja, wenn es *sehr, sehr* viele Treffer sind, vielleicht auch mal 2 oder 3 greps. Aber das Prinzip stimmt.)

Ich hoffe, das hilft Dir noch ein bisschen weiter.

Jochen
Die grösste Lüge der EDV? "Mal eben..."

Post Reply