Grep, ack-grep, find, sort, *.pdf

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
fradie
Beiträge: 20
Registriert: 01.05.2013 21:23:41

Grep, ack-grep, find, sort, *.pdf

Beitrag von fradie » 06.10.2013 19:40:34

Hallo,
lange arbeite ich noch nicht mit der bash, jedenfalls nicht mit regular expressions und komplizierten Suchanfragen. Und da kommt meine Frage her:
Ich möchte meine *.pdf - und *.html - Dateien in einem Ordner mit drei oder vier Unterordnern nach, sagen wir mal 'find' durchsuchen. Die Ausgabe darf gerne Datei und Zeilennummern enthalten und darf auch in .txt umgeleitet werden - mir raucht schon der Kopp! grep und egrep liefern alle nicht befriedigende Ergebnisse, ack-grep kennt *.pdf nicht...
Habt ihr da einen Tipp? Würde mich riesig freuen! :)

Ich bedanke mich schommal für eure Mühen

Dietrich
debian 3.10-2-686-pae #1 SMP Debian 3.10.7-1 (2013-08-17) i686 GNU/Linux

Cae
Beiträge: 6349
Registriert: 17.07.2011 23:36:39
Wohnort: 2130706433

Re: Grep, ack-grep, find, sort, *.pdf

Beitrag von Cae » 06.10.2013 22:34:38

Man muss das auftrennen in zwei Aufgaben:
  1. "finde rekursiv alle Dateien mit Namen *.pdf oder *.html" und
  2. "suche in diesen Dateien nach pattern".
Das laesst sich mit find und grep erledigen, die durch eine Pipe aneinander gehaengt werden:

Code: Alles auswählen

$ find /path -iname '*.pdf' -o -iname '*.html' -print0 | xargs -0 grep -n find >output.txt
-print0 und -0 sorgen dafuer, dass "komische" Dateinamen ohne versehentliches Auftrennen an xargs weitergegeben wird, welches effektiv

Code: Alles auswählen

grep -n find /path/a/foo /path/a/bar /path/b/foo...
startet. -n sorgt fuer Dateiname und Zeilennummer im Output.

Gruss Cae
If universal surveillance were the answer, lots of us would have moved to the former East Germany. If surveillance cameras were the answer, camera-happy London, with something like 500,000 of them at a cost of $700 million, would be the safest city on the planet.

—Bruce Schneier

Benutzeravatar
Phineas
Beiträge: 348
Registriert: 20.06.2012 20:26:19

Re: Grep, ack-grep, find, sort, *.pdf

Beitrag von Phineas » 06.10.2013 22:48:15

Wenn grep mehrere Dateien selbst einliest (also nicht über Pipe bzw. stdin), gibt:

Code: Alles auswählen

grep -n Muster Datei1 Datei2 ...
Dateinamen und Zeilennummern mit aus, wenn "Muster" gefunden wurde.

Bei PDFs wirst Du wohl zumindest mit pdftotext oder vergleichbaren Tools vorarbeiten müssen. Oder ein spezielles "pdf-grep" nutzen (falls es so etwas gibt). Und auch damit gibt es keine Erfolgsgarantie, denn Texte können in PDFs auch als Grafiken vorliegen.

Cae war schneller. find -exec kann xargs hier übrigens ersetzen, wenn anstelle \; ein + benutzt wird.

wanne
Moderator
Beiträge: 7465
Registriert: 24.05.2010 12:39:42

Re: Grep, ack-grep, find, sort, *.pdf

Beitrag von wanne » 06.10.2013 22:57:06

Wprde eher das empfehlen:

Code: Alles auswählen

find /path -iname '*.html' -exec grep -n find {} \; >output.txt
find ./path -iname '*.pdf' -exec echo "pdf2txt {} | grep -q find && echo {}" \; | bash 2> /dev/null >output2.txt
Denn pdf sind nciht im klartext und find findet mitunter sehr viele Dateien. – Zu vile für xargs.
Allerdings: pdf zu dursuchen ist langwierig.

Edit: Phineas war großteils schneller
rot: Moderator wanne spricht, default: User wanne spricht.

Benutzeravatar
Phineas
Beiträge: 348
Registriert: 20.06.2012 20:26:19

Re: Grep, ack-grep, find, sort, *.pdf

Beitrag von Phineas » 06.10.2013 23:05:22

Du hast Deine Befehle nicht getestet, gelle wanne? Die liefern keinen Dateinamen. Warum, steht in meinem Beitrag ("mehrere Dateien"). Im Ersten Befehl brauchst Du nur das \; ersetzen.

Cae
Beiträge: 6349
Registriert: 17.07.2011 23:36:39
Wohnort: 2130706433

Re: Grep, ack-grep, find, sort, *.pdf

Beitrag von Cae » 06.10.2013 23:22:22

Gerade weil find vermutlich einen Riesenhaufen Dateien ausgibt, wuerde ich xargs verwenden. Sonst hat man fuer jede Datei einen fork() fuer ein eigenes grep, womoeglich sogar noch mit sh -c. Da ist es garantiert performanter ein einzelnes grep einige wenige Male zu starten, aber mit 50 Dateien als Argument.

Gruss Cae
If universal surveillance were the answer, lots of us would have moved to the former East Germany. If surveillance cameras were the answer, camera-happy London, with something like 500,000 of them at a cost of $700 million, would be the safest city on the planet.

—Bruce Schneier

Benutzeravatar
Phineas
Beiträge: 348
Registriert: 20.06.2012 20:26:19

Re: Grep, ack-grep, find, sort, *.pdf

Beitrag von Phineas » 07.10.2013 00:45:34

Cae hat geschrieben:Sonst hat man fuer jede Datei einen fork() fuer ein eigenes grep, womoeglich sogar noch mit sh -c.
Woran liegt es, dass meine Posts nicht gelesen werden? Zum 3. Mal: das + macht den Unterschied. Beweis:

Code: Alles auswählen

~> mkdir testordner
~> cd testordner/
~/testordner> # 200 Testdateien erstellen:
~/testordner> for f in {1..200}; do >$f; done
~/testordner> # mit fork:
~/testordner> find ./ -type f -exec echo {} \;
./105
./128
./33
[gekürzt]
./121
./80
./160
~/testordner> # ohne fork:
~/testordner> find ./ -type f -exec echo {} +
./105 ./128 ./33 ./116 ./31 ./171 ./161 ./17 ./101 ./149 ./136 ./152 ./122 ./10 ./40 ./102 ./195 ./61 ./35 ./26 ./115 ./107 ./145 ./132 ./112 ./25 ./16 ./64 ./151 ./3 ./177 ./179 ./84 ./131 ./9 ./93 ./111 ./72 ./73 ./159 ./125 ./191 ./141 ./32 ./104 ./75 ./88 ./126 ./127 ./147 ./58 ./106 ./97 ./163 ./189 ./90 ./95 ./200 ./114 ./8 ./119 ./150 ./39 ./44 ./182 ./185 ./21 ./192 ./2 ./70 ./6 ./174 ./67 ./165 ./76 ./167 ./60 ./142 ./65 ./198 ./113 ./103 ./1 ./36 ./176 ./11 ./196 ./91 ./29 ./52 ./156 ./85 ./38 ./170 ./89 ./188 ./183 ./137 ./98 ./37 ./5 ./20 ./180 ./15 ./56 ./194 ./193 ./63 ./169 ./87 ./34 ./140 ./118 ./69 ./12 ./133 ./138 ./173 ./28 ./77 ./184 ./49 ./50 ./53 ./45 ./109 ./99 ./129 ./135 ./168 ./74 ./23 ./172 ./18 ./94 ./164 ./178 ./47 ./62 ./100 ./43 ./144 ./153 ./187 ./41 ./46 ./110 ./82 ./24 ./51 ./181 ./158 ./55 ./48 ./134 ./57 ./162 ./54 ./175 ./27 ./86 ./124 ./4 ./14 ./22 ./7 ./146 ./166 ./120 ./68 ./78 ./81 ./108 ./123 ./130 ./42 ./96 ./30 ./79 ./157 ./148 ./117 ./190 ./197 ./186 ./71 ./19 ./92 ./139 ./154 ./66 ./59 ./13 ./199 ./83 ./155 ./143 ./121 ./80 ./160
~/testordner>  

wanne
Moderator
Beiträge: 7465
Registriert: 24.05.2010 12:39:42

Re: Grep, ack-grep, find, sort, *.pdf

Beitrag von wanne » 07.10.2013 04:18:11

Cae hat geschrieben:Gerade weil find vermutlich einen Riesenhaufen Dateien ausgibt, wuerde ich xargs verwenden. Sonst hat man fuer jede Datei einen fork() fuer ein eigenes grep, womoeglich sogar noch mit sh -c. Da ist es garantiert performanter ein einzelnes grep einige wenige Male zu starten, aber mit 50 Dateien als Argument.
Ein fork braucht hier ca. 0,2 ms. Bei der maximalanzahl der Parameter, die mein 64Bit 3.2 Linux schafft sind das dann wirklich über 3 Minuten. Bei nem 2.6.23 32Bit währen es nur 0,6 Sekunden.
Allerdings heißt das noch lange nicht, dass das grep auch wirklich mitmacht. mv verhällt sich z.B. bei mehr als 23693 Parametern komisch. (Das währen mit Fork dann 5 Sekunden.)
Letztendlich wird der fork beim pdf2txt nicht ins gewicht fallen.
Die fork() sparerei ist zwar ein Sport dem auch ich gerne nachhänge sinnvoll ist sie aber glaube ich nicht. Gerade mit mv und xargs hatte ich jetzt schon ein paar mal ärger.
Phineas hat geschrieben:m Ersten Befehl brauchst Du nur das \; ersetzen.
Der 2. Funktioniert schon.
Beim ersten habe ich bei dir kopiert ohne genau hinzusehen gemeint war natürlich das:

Code: Alles auswählen

find /path -iname '*.html' -exec grep -l find {} \; >output.txt
rot: Moderator wanne spricht, default: User wanne spricht.

fradie
Beiträge: 20
Registriert: 01.05.2013 21:23:41

Re: Grep, ack-grep, find, sort, *.pdf

Beitrag von fradie » 07.10.2013 22:41:23

Danke wegen der Mühe, die ihr euch gegeben habt, aber...
Es klappt nicht.
Ich habe xargs gepiped und ich habe -exec getestet, das hatte ich schon vorher. Das Prob ist: find liefert nicht die Ausgaben, die ich brauche. Was ich bekomme, sind Fundstellen von *.html, aber nichts aus den *.pdf-Dateien. Im Ordner -Pfad/Linux/Allgemein befinden sich 3 Ordner und 72 Files - 2 der Ordner sind *.html, der Rest sind *.pdf-Dateien. Ene davon heißt sogar 'grep.pdf, sonst sind da so Sachen wie 'The_Linux_Command_Line' von William E. Shotts - da sollten doch ein paar 'grep' oder 'find' - Fundstellen möglich sein?
'find ~/eBooks/Linux/Allgemein -iname '*.html' -o -iname '*.pdf' -exec grep -n grep {} \; >output.txt' - ergibt leere Datei output.txt
find ~/eBooks/Linux/Allgemein -iname '*.html' -o -iname '*.pdf' -exec grep -n find {} \; >output.txt - dito
find ~/eBooks/Linux/Allgemein -iname '*.pdf' -print0 | xargs -0 grep -n find >output.txt - dito
find ~/eBooks/Linux/Allgemein -iname '*.pdf' -o -iname '*.html' -print0 | xargs -0 grep -n find >output.txt - findet immerhin was in meinen *.html - Dateien...

Ich weiß nix mehr... :?

[oder?]
Das hier hab ich noch getestet: 'find ~/eBooks/Linux/Allgemein -iname '*.pdf' -exec grep -ln grep {} \;
Ausgabe:

Code: Alles auswählen

'/home/fradie/eBooks/Linux/Allgemein/Linux 2011.pdf
/home/fradie/eBooks/Linux/Allgemein/Linux fromScratch -7.3.pdf
/home/fradie/eBooks/Linux/Allgemein/grep.pdf
/home/fradie/eBooks/Linux/Allgemein/Linux from Scratch.pdf
/home/fradie/eBooks/Linux/Allgemein/LINUX - Installation, Konfiguration, Anwendung_noPW.pdf
/home/fradie/eBooks/Linux/Allgemein/SelfLinux-0.13.0-pdf/mplayer.pdf
... wenigstens etwas...
Das hier 'find ~/eBooks/Linux/Allgemein -iname '*.pdf' -exec grep -n grep {} \;' dagegen lieferte dies:
(Ich sage vorher schonmal gute Nacht und danke schön! Ich musste die Ausgabe wg erlaubter 50.000 Zeichen etwas kürzen :) )

Code: Alles auswählen

<</Limits[(table.caption.671)(table.caption.970)]/Names[(table.caption.671)76 0 R (table.caption.677)74 0 R (table.caption.680)72 0 R (table.caption.684)70 0 R (table.caption.687)68 0 R (table.caption.690)66 0 R (table.caption.692)65 0 R (table.caption.694)63 0 R (table.caption.696)61 0 R (table.caption.70)59 0 R (table.caption.700)57 0 R (table.caption.702)55 0 R (table.caption.705)54 0 R (table.caption.707)52 0 R (table.caption.710)50 0 R (table.caption.712)48 0 R (table.caption.716)46 0 R (table.caption.719)44 0 R (table.caption.722)43 0 R (table.caption.724)41 0 R (table.caption.728)40 0 R (table.caption.730)38 0 R 
[...]
 R/Count -5/First 5575 0 R/Last 5569 0 R/Next 5556 0 R/Parent 5498 0 R/Prev 5578 0 R/Title(Teil 1 Einf\374hrung und I<</A 5582 0 R/Count -10/First 5580 0 R/Last 5497 0 R/Next 5482 0 R/Parent 5092 0 R/Prev 5587 0 R/Title(\376\377Inhaltsverzeichni<</A 5602 0 R/F 2/Next 5587 0 R/Parent 5092 0 R/Title(Linux 2011 - Debian, Fedora, openSUSE, Ubuntu - 10., \374berarbeitete und streamter/FlateDecode/Length 1564>>
Übereinstimmungen in Binärdatei /home/fradie/eBooks/Linux/Allgemein/Linux fromScratch -7.3.pdf.
Übereinstimmungen in Binärdatei /home/fradie/eBooks/Linux/Allgemein/grep.pdf.
4524:/A << /URI (http://www.gnu.org/software/grep/)
4535:/A << /URI (http://ftp.gnu.org/gnu/grep/grep-2.5.3.tar.bz2)
5564:/A << /URI (http://www.linuxfromscratch.org/patches/lfs/6.4/grep-2.5.3-debian_fixes-1.patch)
5575:/A << /URI (http://www.linuxfromscratch.org/patches/lfs/6.4/grep-2.5.3-upstream_fixes-1.patch)
Übereinstimmungen in Binärdatei /home/fradie/eBooks/Linux/Allgemein/LINUX - Installation, Konfiguration, Anwendung_noPW.pdf.
Übereinstimmungen in Binärdatei /home/fradie/eBooks/Linux/Allgemein/SelfLinux-0.13.0-pdf/mplayer.pdf.
Damit das hier lesbar bleibt von wanne gekürzt und in Code-Blöcke gesetzt.
Zuletzt geändert von fradie am 07.10.2013 23:09:32, insgesamt 1-mal geändert.
debian 3.10-2-686-pae #1 SMP Debian 3.10.7-1 (2013-08-17) i686 GNU/Linux

Benutzeravatar
Phineas
Beiträge: 348
Registriert: 20.06.2012 20:26:19

Re: Grep, ack-grep, find, sort, *.pdf

Beitrag von Phineas » 07.10.2013 23:09:02

fradie hat geschrieben:find ~/eBooks/Linux/Allgemein -iname '*.pdf' -o -iname '*.html' -print0 | xargs -0 grep -n find >output.txt - findet immerhin was in meinen *.html - Dateien...

Code: Alles auswählen

find ~/eBooks/Linux/Allgemein -iname '*.pdf' -o -iname '*.html' -exec grep -n find {} + >output.txt 
tut das wegen dem Pluszeichen auch, aber ich ich gebe es hier jetzt trotzdem auf.

fradie
Beiträge: 20
Registriert: 01.05.2013 21:23:41

Re: Grep, ack-grep, find, sort, *.pdf

Beitrag von fradie » 07.10.2013 23:26:28

SOrry,
aber deinen Vorschlag mit dem '+' hatte ich auch getestet - mit dem Ergebnis, dass 'find' nur die *.html - Dateien durchsuchte ...
Danke trotzdem!

Dietrich
debian 3.10-2-686-pae #1 SMP Debian 3.10.7-1 (2013-08-17) i686 GNU/Linux

wanne
Moderator
Beiträge: 7465
Registriert: 24.05.2010 12:39:42

Re: Grep, ack-grep, find, sort, *.pdf

Beitrag von wanne » 08.10.2013 13:05:50

Und jetzt nochmal: PDF haben:
1. Keine Zeilen nur Positionen. => Es kann keine Zeilenangaben geben
2. Sind sie nicht im Klartext. => Man sollte nicht einfach mit grep drüber fahren.

Deswegen kam 23min nach Caes Vorschlag einer von mir der das Behebt und eben keine Zeilen angibt.
In dem war allerdings ein kleiner Fehler (statt einem l gab ich ein n mit.) Phineas verbesserte das weitere 14 Minuten späer. (Im übrigen noch sehr ellegant sodass der schneller läuft und sauberere Ergebnisse bringt als mein Ursprünglich gedachter.) Also hat es insgesammt nichteinmal eine halbe Stunde gedauert, bis ein sauberer Vorschlag da war.

Über 24h später fallen die Fehler das dann auch dem Fragesteller auf. Aber statt die Beiträge etwas genauer zu lesen wird einfach mal eine 10-Seitige Fehlermeldung gepostst.
Kann ja nciht sein, dass niemand den Befehl am stück postet und man auchnoch außerhalb der Code-blöcke lesen muss.
rot: Moderator wanne spricht, default: User wanne spricht.

tobo
Beiträge: 1993
Registriert: 10.12.2008 10:51:41

Re: Grep, ack-grep, find, sort, *.pdf

Beitrag von tobo » 08.10.2013 13:46:42

fradie hat geschrieben:SOrry,
aber deinen Vorschlag mit dem '+' hatte ich auch getestet - mit dem Ergebnis, dass 'find' nur die *.html - Dateien durchsuchte ...
Das ist auch kein Wunder, da die Oder-Verknüpfung die komplette Parameterliste zweiteilt. Entweder musst Du die Parameter auf beiden Seiten des Oders gleichsetzen oder Du musst das entsprechende Oder klammern:

Code: Alles auswählen

>$ find . -iname '*.pdf' | wc -l
192
>$ find . -iname '*.html' | wc -l
5645
>$ find . -iname '*.pdf' -o -iname '*.html' | wc -l
5837

>$ find . -iname '*.pdf' -o -iname '*.html' -print | wc -l
5645
>$ find . -iname '*.html' -o -iname '*.pdf' -print | wc -l
192

>$ find . \( -iname '*.pdf' -o -iname '*.html' \) -print | wc -l
5837
>$ find . -iname '*.pdf' -print -o -iname '*.html' -print | wc -l
5837

Benutzeravatar
CH777
Beiträge: 1466
Registriert: 27.05.2008 16:37:17

Re: Grep, ack-grep, find, sort, *.pdf

Beitrag von CH777 » 08.10.2013 14:24:57

Phineas hat geschrieben:Oder ein spezielles "pdf-grep" nutzen (falls es so etwas gibt).
Gibt es tatsächlich: Debianpdfgrep

fradie
Beiträge: 20
Registriert: 01.05.2013 21:23:41

Re: Grep, ack-grep, find, sort, *.pdf

Beitrag von fradie » 08.10.2013 21:20:20

@ wanne:
sorry, hatte wohl 'n stack overflow - jetzt kapier ichs endlich.
@ tobo und phineas:
pdfgrep ist der Hammer! Klasse Tipp, thx.
Mit einem einfachen
pdfgrep -rnH '\<find\>' . war das Problem gelöst! :D
debian 3.10-2-686-pae #1 SMP Debian 3.10.7-1 (2013-08-17) i686 GNU/Linux

Antworten