Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

pdfgrep an evince...

45 views
Skip to first unread message

Patrick Rudin

unread,
Jun 6, 2022, 9:17:12 AM6/6/22
to
Ich benutze gelegentlich pdfgrep, um in einem Verzeichnis alle
pdf-Dateien nach einem Wort zu durchsuchen.

pdfgrep -m 1 blabla verzeichnis/*.pdf

gibt so alle Treffer mit Dateiname und der gesamten gefundenen Zeile
aus. Das -m 1 sorgt dafür, dass nur der jeweils erste Treffer angegeben
wird, jede Datei also nur einmal genannt wird.

Nun würde ich das gerne per Pipe weiterleiten, damit Evince oder ein
anderer pdf-Reader jeweils direkt alle Dateien öffnet. Wie lautet da die
Syntax?

Evince verträgt es, wenn man ihm direkt mehrere Dateinamen aneinander
gereiht vorwirft, er öffnet sie jeweils als weitere Instanz.


Grüsse

Patrick

Tim Landscheidt

unread,
Jun 6, 2022, 10:39:49 AM6/6/22
to
Ich kenne Evince nicht, aber das sollte mit:

| pdfgrep -Z -l blabla verzeichnis/*.pdf | xargs -0r evince

funktionieren. Falls die Pipe stört, kann man das auch à
la:

| find verzeichnis -maxdepth 1 -type f -name \*.pdf -exec pdfgrep -q blabla {} \; -exec evince +

umschreiben.

Tim

Christian Garbs

unread,
Jun 6, 2022, 10:47:31 AM6/6/22
to
Mahlzeit!

Patrick Rudin <tax...@gmx.ch> wrote:

> pdfgrep -m 1 blabla verzeichnis/*.pdf
>
> gibt so alle Treffer mit Dateiname und der gesamten gefundenen Zeile
> aus.

> Das -m 1 sorgt dafür, dass nur der jeweils erste Treffer angegeben
> wird, jede Datei also nur einmal genannt wird.

Den Treffer selbst brauchst Du ja nicht und Du hast jetzt vermutlich
ein Problem, den Dateinamen vom Treffer zu unterscheiden. Mögliche
Leerzeichen im Dateinamen machen das nicht einfacher :-)

Daher:

1. nur den Dateinamen ausgeben lassen
2. \0 als Trennzeichen nehmen

> Nun würde ich das gerne per Pipe weiterleiten, damit Evince oder ein
> anderer pdf-Reader jeweils direkt alle Dateien öffnet. Wie lautet da die
> Syntax?

Ich habe pdfgrep nicht installiert, aber wenn ich die Online-Manpage
unter https://pdfgrep.org/doc.html angucke, dann dürften für Dich "-l"
und "-Z" interessant sein.

Probier mal "pdfgrep -lZ foo *.pdf | xargs -0 evince".

Gruß
Christian
--
....Christian.Garbs....................................https://www.cgarbs.de
"MegaTokyo, the comic: I've been working on a little side project - a small
project that isn't supposed to take away from the time i spend on other
things" - Fred Gallagher, may 16, 2000 talking about the start of Megatokyo.

Patrick Rudin

unread,
Jun 6, 2022, 11:14:55 AM6/6/22
to
Tim Landscheidt wrote:
> | pdfgrep -Z -l blabla verzeichnis/*.pdf | xargs -0r evince

Ah, xargs, danke.

Ich hab keine Leerzeichen in den Dateinamen, daher tut es ein
pdfgrep -il blabla verzeichnis/*.pdf | xargs evince

perfekt, bei mehreren Treffern macht er so mehrere Fenster auf.

Danke auch Christian.


Gruss

Patrick

Patrick Rudin

unread,
Jun 6, 2022, 4:38:37 PM6/6/22
to
Patrick Rudin wrote:
> pdfgrep -il blabla verzeichnis/*.pdf | xargs evince

Zusatzfrage: Wie kann ich die ausgewählten Dateien auf ein weiteres
Stichwort durchsuchen? Mit -e scheint es lediglich or-Verknüpfungen zu
geben.

Ein
pdfgrep -il blabla verzeichnis/*.pdf | pdfgrep -i blubber -
oder ähnliche Varianten funktionieren jedenfalls nicht...


Grüsse

Patrick

Andreas Karrer

unread,
Jun 6, 2022, 4:54:54 PM6/6/22
to
* Patrick Rudin <tax...@gmx.ch>:
xargs hat ja vorhin schon geholfen. Mal versuchen zu verstehen, wie
xargs funktioniert.

pdfgrep -il blabla verzeichnis/*.pdf | xargs pdfgrep -il blubber | xargs evince


- Andi

Patrick Rudin

unread,
Jun 6, 2022, 6:07:44 PM6/6/22
to
Andreas Karrer wrote:
> xargs hat ja vorhin schon geholfen. Mal versuchen zu verstehen, wie
> xargs funktioniert.

Ich verstehe die Funktionsweise der Pipe nicht. Warum kann ich ein
simples grep hinter die Pipe setzen, und dann wird der Output gefiltert
(hier halt nur zeilenweise), während ein pdfgrep zusätzlich ein xargs
braucht, um die übergebenen Dateinamen als Input zu akzeptieren?

> pdfgrep -il blabla verzeichnis/*.pdf | xargs pdfgrep -il blubber | xargs evince

Danke, funktioniert. Wirklich verstehen tu ich es aber nicht.


Gruss

Patrick

Diedrich Ehlerding

unread,
Jun 7, 2022, 1:42:43 AM6/7/22
to
Patrick Rudin meinte:

>> xargs hat ja vorhin schon geholfen. Mal versuchen zu verstehen, wie
>> xargs funktioniert.
>
> Ich verstehe die Funktionsweise der Pipe nicht. Warum kann ich ein
> simples grep hinter die Pipe setzen, und dann wird der Output
> gefiltert (hier halt nur zeilenweise), während ein pdfgrep zusätzlich
> ein xargs braucht, um die übergebenen Dateinamen als Input zu
> akzeptieren?

Der Output des ersten pdfgrep sind Datei_namen_. Du willst nicht diesen
Output (also die Namen) durchflöhen, sondern die Dateien, auf die diese
Namen verweisen
>
--
gpg-Key (DSA 1024) D36AD663E6DB91A4
fingerprint = 2983 4D54 E00B 8483 B5B8 C7D1 D36A D663 E6DB 91A4
HTML-Mail wird ungeleſen entſorgt.

Helmut Waitzmann

unread,
Jun 7, 2022, 2:51:57 AM6/7/22
to
Patrick Rudin <tax...@gmx.ch>:

>Ich verstehe die Funktionsweise der Pipe nicht. Warum kann ich ein
>simples grep hinter die Pipe setzen, und dann wird der Output
>gefiltert (hier halt nur zeilenweise), während ein pdfgrep
>zusätzlich ein xargs braucht, um die übergebenen Dateinamen als
>Input zu akzeptieren?

Den von dir vermuteten Unterschied zwischen den Programmen «grep»
und «pdfgrep» gibt es nicht.  Der Unterschied zwischen den beiden
Anwendungsfällen oben besteht darin, dass einem Programm (hier:
«(pdf‐)grep») Daten in einem Fall (ohne «xargs») als Eingabe
geliefert und im anderen Fall (mit «xargs») als Aufrufparameter
übergeben werden sollen.

Wenn du ein «(pdf‐)grep» aus einem Pipe fütterst, filtert
«(pdf‐)grep» das, was es aus dem Pipe als Eingabe erhält.  (Dabei
sollte die Eingabe bei «pdfgrep» ein PDF‐Dokument und bei «grep» ein
Plain‐Text‐Dokument sein.)

Wenn du ein «xargs» aus einem Pipe fütterst und damit «(pdf‐)grep»
startest, liest «xargs» Daten aus dem Pipe (in deinem
Anwendungsfall: Dateinamen) und startet damit «(pdf‐)grep» mit den
Dateinamen als Parametern.  Das tut «xargs» allerdings nur dann
zuverlässig, wenn du, wie Tim und Christian dir nahegelegt haben,
bei «(pdf‐)grep» die Optionen «-l» und «-Z» und bei «xargs» die
Optionen «-0» und «-r» verwendest.

Wenn du «xargs» ohne «-0» und «-r» betreiben willst, musst du jeden
Dateinamen, bevor du ihn an «xargs» verfütterst, noch durch einen
speziellen Präprozessor jagen, den du zuerst noch entwickeln
müsstest.  Das ist zwar machbar, aber aufwendig.

Nicht ohne Grund gibt es die «(pdf‐)grep»‐Optionen «-l» und «-Z» und
die «xargs»‐Optionen «-0» und «-r».  Nütze sie ohne Wenn und Aber. 
(Wenn dich Einzelheiten interessieren, frag gerne danach.  Das wäre
dann eine Diskussion in «de.comp.os.unix.programming» oder
«de.comp.os.unix.misc» wert.)

Lies ein gutes Buch über die Funktionsweise bzw. die
Systemaufruf‐Schnittstelle (hier speziell die Systemaufrufe «pipe»,
«fork» und «execve») von Unix oder Linux.  Bücher der Art «So
funktioniert die Bash», «Die wichtigsten Shell‐Kommandos, einfach
erklärt» (o. ä.) oder auch das Handbuch «bash(1)» helfen dir da
nicht weiter, denn sie setzen im Grund alle voraus, dass du die
Systemaufrufe, die dir Unix oder Linux bereitstellt, bereits kennst.

Stefan Froehlich

unread,
Jun 7, 2022, 3:28:58 AM6/7/22
to
On Tue, 07 Jun 2022 00:07:41 Patrick Rudin wrote:
> Andreas Karrer wrote:
>> xargs hat ja vorhin schon geholfen. Mal versuchen zu verstehen, wie
>> xargs funktioniert.

> Ich verstehe die Funktionsweise der Pipe nicht. Warum kann ich ein
> simples grep hinter die Pipe setzen, und dann wird der Output
> gefiltert (hier halt nur zeilenweise), während ein pdfgrep
> zusätzlich ein xargs braucht, um die übergebenen Dateinamen als
> Input zu akzeptieren?

Der Einfachheit halber mit Textdateien erklärt:

$ grep foo *.txt

gibt Dir alle Zeilen zurück, die foo enthalten. Möchtest Du darin
weitersuchen (alle Zeilen mit foo und bar), reicht eine Verkettung
mit dem nächsten grep:

$ grep foo *.txt | grep bar

Im Unterschied dazu gibt -l nur die Liste der Dateien mit Treffern
zurück:

$ grep -l foo *.txt

Wenn Du darin mit einer pipe weitersuchst:

$ grep -l foo *.txt | grep bar

...bekommst Du konsequenterweise aller *Dateinamen* (der Dateien, in
denen foo enthalten ist), die bar enthalten.

Mit xargs nimmst Du hingegen das Ergebnis und fütterst es als
Argument in das nächste Programm:

$ grep foo -l *.txt | xargs grep bar

...ist also das gleiche wie:

grep file_1.txt file_2.txt file_3.txt bar

...unter der Voraussetzung, dass file_1 bis file_3 die Dateien sind,
die bei der Suche nach bar gefunden wurden.


Hat man das erst einmal verinnerlicht, erzeugt man sehr bald
ziemlich lange, aber auch ziemlich mächtige Befehlszeilen :-)

Servus,
Stefan

--
http://kontaktinser.at/ - die kostenlose Kontaktboerse fuer Oesterreich
Offizieller Erstbesucher(TM) von mmeike

Jubel der werbegläubigen Herzen. Mit Stefan. Ein kultiviertes Vergnügen!
(Sloganizer)

Helmut Waitzmann

unread,
Jun 7, 2022, 6:19:32 AM6/7/22
to
Stefan...@Froehlich.Priv.at (Stefan Froehlich):
>On Tue, 07 Jun 2022 00:07:41 Patrick Rudin wrote:
>
>> Ich verstehe die Funktionsweise der Pipe nicht. Warum kann ich
>> ein simples grep hinter die Pipe setzen, und dann wird der Output
>> gefiltert (hier halt nur zeilenweise), während ein pdfgrep
>> zusätzlich ein xargs braucht, um die übergebenen Dateinamen als
>> Input zu akzeptieren?
>
>Der Einfachheit halber mit Textdateien erklärt:
>
>
>$ grep foo *.txt
>
>gibt Dir alle Zeilen zurück, die foo enthalten. Möchtest Du darin
>weitersuchen (alle Zeilen mit foo und bar), reicht eine Verkettung
>mit dem nächsten grep:
>
>$ grep foo *.txt | grep bar
>
>Im Unterschied dazu gibt -l nur die Liste der Dateien mit Treffern
>zurück:
>
>$ grep -l foo *.txt
>
>Wenn Du darin mit einer pipe weitersuchst:
>
>
>$ grep -l foo *.txt | grep bar
>
>...bekommst Du konsequenterweise aller *Dateinamen* (der Dateien,
>in denen foo enthalten ist), die bar enthalten.
>
>Mit xargs nimmst Du hingegen das Ergebnis und fütterst es als
>Argument in das nächste Programm:

Besser:  Mit «xargs» nimmst du hingegen das Ergebnis und gibst es
dem nächsten Programm in seiner Aufrufparameterliste mit:

>
>$ grep foo -l *.txt | xargs grep bar

Das scheitert mit einem Nicht‐GNU‐«grep» in der Regel (und mit
GNU‐«grep» je nachdem, wie die von «*.txt» erfassten Dateien
heißen).  Nimm lieber


grep -l -- foo *.txt | xargs -- grep -- bar

und, wie andernorts bereits geschrieben:  Wenn vorhanden – und das
ist bei GNU der Fall –, nimm

grep -lZ -- foo *.txt | xargs -0 -r -- grep bar

ohne Wenn und Aber.  Die 13 Zeichen mehr Tipparbeit sollte es dir
wert sein.

Grundregeln bei Programmen, die nach den
Standard‐Aufrufsyntax‐Regeln
(<https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html#tag_12_02>)
arbeiten (das ist bei den moderneren Programmen meistens der Fall):

Als erstes in der Parameterliste kommen die Optionen (mit ihren
Parametern, sofern sie welche haben).  Dann folgt die spezielle
Optionen‐Ende‐Option «--».  Dann erst folgen
Nicht‐Optionen‐Parameter (Dateinamen, andere Zeichenketten…).

Die spezielle Optionen‐Ende‐Option lässt man selbst dann nicht weg,
wenn man (im Augenblick) der Überzeugung ist, man brauche sie in
diesem speziellen Fall nicht:  Erstens kann man sich täuschen,
zweitens erst recht dann, wenn man nach Jahren im Shell‐Skript
Änderungen vornimmt und dabei übersieht, dass der «spezielle Fall»
nach den erfolgten Änderungen nicht mehr vorliegt.

>
>...ist also das gleiche wie:
>
>grep file_1.txt file_2.txt file_3.txt bar
>

Nicht ganz, sondern vielmehr hängt «xargs» die von ihm ermittelten
Parameter hinten dran:

grep bar file_1.txt file_2.txt file_3.txt


>...unter der Voraussetzung, dass file_1 bis file_3 die Dateien
>sind, die bei der Suche nach bar gefunden wurden.
>
>
>Hat man das erst einmal verinnerlicht, erzeugt man sehr bald
>ziemlich lange, aber auch ziemlich mächtige Befehlszeilen :-)

Ja.  Sichere aber nur, wenn man die angeführten Vorsichtsmaßnahmen
ernstnimmt.

Peter Heitzer

unread,
Jun 7, 2022, 9:04:57 AM6/7/22
to
Helmut Waitzmann <nn.th...@xoxy.net> wrote:
>Stefan...@Froehlich.Priv.at (Stefan Froehlich):
>>On Tue, 07 Jun 2022 00:07:41 Patrick Rudin wrote:
>>
>>> Ich verstehe die Funktionsweise der Pipe nicht. Warum kann ich
>>> ein simples grep hinter die Pipe setzen, und dann wird der Output
>>> gefiltert (hier halt nur zeilenweise), während ein pdfgrep
>>> zusätzlich ein xargs braucht, um die übergebenen Dateinamen als
>>> Input zu akzeptieren?
>>
>>Der Einfachheit halber mit Textdateien erklärt:
>>
>>
>>$ grep foo *.txt
>>
>>gibt Dir alle Zeilen zurück, die foo enthalten. Möchtest Du darin
>>weitersuchen (alle Zeilen mit foo und bar), reicht eine Verkettung
>>mit dem nächsten grep:
>>
>>$ grep foo *.txt | grep bar
Oder gleich ein grep verwenden, das Regexes beherrscht.
$ grep -E "foo|bar" *.txt
bei Gnu grep

--
Dipl.-Inform(FH) Peter Heitzer, peter....@rz.uni-regensburg.de

Patrick Rudin

unread,
Jun 7, 2022, 11:28:40 AM6/7/22
to
Helmut Waitzmann wrote:
> Den von dir vermuteten Unterschied zwischen den Programmen «grep» und
> «pdfgrep» gibt es nicht.  Der Unterschied zwischen den beiden
> Anwendungsfällen oben besteht darin, dass einem Programm (hier:
> «(pdf‐)grep») Daten in einem Fall (ohne «xargs») als Eingabe geliefert
> und im anderen Fall (mit «xargs») als Aufrufparameter übergeben werden
> sollen.

Ah. Die Rohre unterscheiden also verschiedene Kategorien von Parametern,
während bei der manuellen Eingabe aus Komfortgründen die Syntax nicht so
eng gesehen wird?

Ich habe mich die letzten Monate intensiv mit R auseinandergesetzt, dort
kann man (mit tidyverse) simpelste Ketten bilden. Aber dabei werden
faktisch immer Vektoren übergeben, formal also immer dasselbe.
Möglicherweise resultiert meine Verwirrung daher.

> Wenn du ein «xargs» aus einem Pipe fütterst und damit «(pdf‐)grep»
> startest, liest «xargs» Daten aus dem Pipe (in deinem Anwendungsfall:
> Dateinamen) und startet damit «(pdf‐)grep» mit den Dateinamen als
> Parametern.  Das tut «xargs» allerdings nur dann zuverlässig, wenn du,
> wie Tim und Christian dir nahegelegt haben, bei «(pdf‐)grep» die
> Optionen «-l» und «-Z» und bei «xargs» die Optionen «-0» und «-r»
> verwendest.

Die Zusatzoptionen habe ich auf Anhieb nicht ohne Syntaxfehler zum
Laufen gebracht, aber das muss ich gelegentlich in Ruhe anschauen.

> Lies ein gutes Buch über die Funktionsweise bzw. die
> Systemaufruf‐Schnittstelle (hier speziell die Systemaufrufe «pipe»,
> «fork» und «execve») von Unix oder Linux.

Ich bin für konkrete Literaturtipps dankbar. Die Fülle an Unix-Büchern
jeglichen Jahrgangs in den hiesigen Bibliotheken ist unüberschaubar.


Gruss

Patrick

Patrick Rudin

unread,
Jun 7, 2022, 11:36:02 AM6/7/22
to
Peter Heitzer wrote:
> Oder gleich ein grep verwenden, das Regexes beherrscht.
> $ grep -E "foo|bar" *.txt
> bei Gnu grep

Das ist aber ein "or", alle Beispiele hier im Thread gehen aber von
einem "and" aus.

Wenn ich das richtig verstanden habe, ist das mit Regexp keineswegs
trivial umzusetzen:
https://stackoverflow.com/questions/469913/regular-expressions-is-there-an-and-operator


Gruss

Patrick

Helmut Waitzmann

unread,
Jun 7, 2022, 11:52:24 AM6/7/22
to
"Peter Heitzer" <peter....@rz.uni-regensburg.de>:

>Oder gleich ein grep verwenden, das Regexes beherrscht.
>$ grep -E "foo|bar" *.txt
>bei Gnu grep
>

Jedes zum POSIX‐Standard kompatible «grep» beherrscht Reguläre
Ausdrücke
(<https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09>)
im Suchmuster, nicht nur GNU‐«grep»:

mit der Option «-F» das Filtern mit wörtlichen Zeichenketten,

mit der Option «-E» das Filtern mit Erweiterten Regulären Ausdrücken
(<https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_04>)

und ohne beide Optionen das Filtern mit Grundlegenden Regulären
Ausdrücken
(<https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_03>).

Gibt es denn heutzutage in freier Wildbahn (außer im
Computer‐Museum) überhaupt noch «grep»‐Implementierungen, die das
nicht beherrschen?


>$ grep -E "foo|bar" *.txt

Das gibt von allen übergebenen Dateien die Zeilen aus, die auf
wenigstens einen der beiden Regulären Ausdrücke, «foo» oder «bar»,
passen.

Beispiel:  In einem leeren Verzeichnis das folgende Kommando laufen
lassen:

(
set -- foo bar &&
for muster
do
printf '%s\n' "$1" > "$1".txt
printf '%s\n' "$1" > no_"$2".txt
printf '%s\n' "${1}${2}" > "${1}${2}".txt
set -- "$@" "$1"
shift
done
)


Dann die folgenden Kommandos probieren:


grep -- foo *.txt
grep -- bar *.txt
grep -- foo *.txt | grep -- bar
grep -E -- 'foo|bar' *.txt
grep -e foo -e bar -- *.txt

Thomas Dorner

unread,
Jun 7, 2022, 1:38:03 PM6/7/22
to
Patrick Rudin <tax...@gmx.ch> writes:
> Peter Heitzer wrote:
>> Oder gleich ein grep verwenden, das Regexes beherrscht.
>> $ grep -E "foo|bar" *.txt
>> bei Gnu grep
>
> Das ist aber ein "or", alle Beispiele hier im Thread gehen aber von
> einem "and" aus.
>
> Wenn ich das richtig verstanden habe, ist das mit Regexp keineswegs
> trivial umzusetzen:

Trivial nicht, aber auch nicht schwierig:

grep -E '(foo.*bar)|(bar.*foo)' *.txt

Viele Grüße, Thomas
--
Adresse gilt nur kurzzeitig!

Stefan Froehlich

unread,
Jun 7, 2022, 2:10:29 PM6/7/22
to
On Tue, 07 Jun 2022 15:04:54 Peter Heitzer wrote:
>>Stefan...@Froehlich.Priv.at (Stefan Froehlich):
>>>$ grep foo *.txt | grep bar

> Oder gleich ein grep verwenden, das Regexes beherrscht.
> $ grep -E "foo|bar" *.txt
> bei Gnu grep

Das ist zum einen etwas anderes (oder statt und), und zum zweiten
auch aus anderen Gründen nicht immer das, was ich haben möchte.
Häufigster Anwendungsfall für grep ist bei mir interaktiv auf der
Befehlszeile, um gezielt Dateien aus einem Verzeichnisbaum zum
Bearbeiten, Vergleichen, whatever herauszupicken. In den seltensten
Fällen weiss ich dabei vorher, wonach *genau* ich suche, sondern
beginne einmal mit

$ find . -type f | xargs grep foo

Das Suchmuster wird dann verfeinert, idR kommen am Ende weitere
Suchmuster hinzu, und ganz am Ende steht dann z.B. so etwas da:

$ vi `find . -type f | xargs grep foo | ... | xargs grep -l bar`

Da kommt es sicherlich vor, dass ich mehrere Ausdrücke
zusammenfassen, einfacher oder eleganter schreiben könnte.
Es bringt mir halt nichts, weil ich die Kombination ab genau
dem Zeitpunkt nicht mehr benötige, zu dem ich die Spezifikation
fertig hätte.

Servus,
Stefan

--
http://kontaktinser.at/ - die kostenlose Kontaktboerse fuer Oesterreich
Offizieller Erstbesucher(TM) von mmeike

Die Macht zu verführen, oder warum Stefan so leis hüpft!
(Sloganizer)

Stefan Froehlich

unread,
Jun 7, 2022, 2:16:19 PM6/7/22
to
On Tue, 07 Jun 2022 17:28:37 Patrick Rudin wrote:
> Helmut Waitzmann wrote:
>> Den von dir vermuteten Unterschied zwischen den Programmen «grep»
>> und «pdfgrep» gibt es nicht.  Der Unterschied zwischen den beiden
>> Anwendungsfällen oben besteht darin, dass einem Programm (hier:
>> «(pdf‐)grep») Daten in einem Fall (ohne «xargs») als Eingabe
>> geliefert und im anderen Fall (mit «xargs») als Aufrufparameter
>> übergeben werden sollen.

> Ah. Die Rohre unterscheiden also verschiedene Kategorien von
> Parametern, während bei der manuellen Eingabe aus Komfortgründen
> die Syntax nicht so eng gesehen wird?

Die Pipe selber unterscheidet gar nicht, nein, die liefert immer
nach stdin. Um davon bei Bedarf loszukommen gibt es xargs(1), das
die eigentliche Magie durchführt: Es liest (sehr grob gesagt) stdin
ein, pappt die darin enthaltenen Daten als Argumente an die im
Anschluss folgende Befehlszeile und führt das Ergebnis aus.

(Disclaimer, bevor wieder jemand mit den Details ankommt: Es tut das
viel besser und kann noch einiges mehr, aber das Grundkonzept steckt
im obigen Absatz)

Servus,
Stefan

--
http://kontaktinser.at/ - die kostenlose Kontaktboerse fuer Oesterreich
Offizieller Erstbesucher(TM) von mmeike

Stefan - die erfolgreichste Steigerungsform von topfit!
(Sloganizer)

Patrick Rudin

unread,
Jun 7, 2022, 2:33:15 PM6/7/22
to
Thomas Dorner wrote:
> Patrick Rudin <tax...@gmx.ch> writes:
>> Das ist aber ein "or", alle Beispiele hier im Thread gehen aber von
>> einem "and" aus.
>>
>> Wenn ich das richtig verstanden habe, ist das mit Regexp keineswegs
>> trivial umzusetzen:
>
> Trivial nicht, aber auch nicht schwierig:
>
> grep -E '(foo.*bar)|(bar.*foo)' *.txt

Das sind aber erweiterte Regexp, die pdfgrep leider nicht zur Verfügung
stehen...


Gruss

Patrick

Helmut Waitzmann

unread,
Jun 7, 2022, 5:52:42 PM6/7/22
to
Patrick Rudin <tax...@gmx.ch>:
>Helmut Waitzmann wrote:
>> Den von dir vermuteten Unterschied zwischen den Programmen «grep»
>> und «pdfgrep» gibt es nicht.  Der Unterschied zwischen den beiden
>> Anwendungsfällen oben besteht darin, dass einem Programm (hier:
>> «(pdf‐)grep») Daten in einem Fall (ohne «xargs») als Eingabe
>> geliefert und im anderen Fall (mit «xargs») als Aufrufparameter
>> übergeben werden sollen.
>
>Ah. Die Rohre unterscheiden also verschiedene Kategorien von
>Parametern, während bei der manuellen Eingabe aus Komfortgründen die
>Syntax nicht so eng gesehen wird?

Ich bin mir jetzt nicht sicher, ob ich dich richtig verstehe:  Pipes
sind dazu da, zwei Prozesse (also laufende Programme) so miteinander
zu verbinden, dass der erste seine Ausgabe nicht auf den Bildschirm
gibt und der zweite seine Eingabe nicht von der Tastatur erhält,
sondern der erste seine Ausgabe direkt an den zweiten reicht, der
sie als Eingabe verwendet.

Pipes kümmern sich um die Daten, die durch sie laufen, nicht.  Es
ist ihnen egal, ob man ein PDF‐Dokument, einen Plain‐Text,
irgendwelche Binär‐Daten, Bilder, … durchschiebt.

Das Shell‐Kommando

erstes_Programm | zweites_Programm

veranlasst den Shell, den Ausgabekanal des ersten Programms mit dem
Eingabekanal des zweiten Programms zu verbinden:  Was das erste
Programm schreibt, kann das zweite lesen.

Beispiel:

Das Shell‐Kommando

printf '%s\n' 'Hallo, Welt!' 'Hello, world!'

gibt eine zweizeilige Ausgabe, bestehend aus der ersten Zeile
«Hallo, Welt!» und der zweiten «Hello, world!'», im Terminal aus. 
Verbindet man seinen Ausgabekanal über ein Pipe mit dem Eingabekanal
von «grep», geht die Ausgabe nicht mehr ins Terminal sondern ins
Pipe und von dort zum Programm «grep»:

printf '%s\n' 'Hallo, Welt!' 'Hello, world!' | grep -F -- 'Hallo'

«grep» liest also die Zeile «Hallo, Welt!» und schaut, ob in ihr das
Wort «Hallo», das es als Parameter erhalten hat, vorkommt.  Kommt es
darin vor, gibt es die Zeile seinerseits aus; kommt es nicht darin
vor, gibt es die Zeile nicht aus sondern wirft sie einfach weg. 
Dasselbe macht «grep» auch mit der zweiten Zeile, «Hello, world!».

Die Folge:  «grep» gibt nur die Zeile «Hallo, Welt!» aus und
verschluckt die Zeile «Hello, world!».

Wenn man «grep» die Option «-l» verpasst, spuckt es die mit dem
Suchmuster übereinstimmenden Zeilen nicht aus sondern nur die Namen
der Dateien, in denen es die übereinstimmenden Zeilen gefunden hat.

Beispiel:  Lasse in einem leeren Verzeichnis das folgende Kommando
laufen:

(
set -- foo bar &&
for muster
do
printf '%s\n' "$1" > "$1".txt
printf '%s\n' "$1" > "no $2".txt
printf '%s\n' "${1} ${2}" > "${1} ${2}".txt
set -- "$@" "$1"
shift
done
)

Das legt dir in dem Verzeichnis die Dateien «foo.txt», «no foo.txt»,
«foo bar.txt», «bar.txt», «no bar.txt» und «bar foo.txt» an.


Lass dir den (einzeiligen) Inhalt einer jeden Datei zeigen:


(
for datei in *.txt
do
printf '\nInhalt der Datei %s:\n' "$datei"
cat -- "$datei"
done
)


Wenn du jetzt das Kommando


grep -l -- foo *.txt

aufrufst, spuckt «grep» wegen der Option «-l» nicht die
Dateiinhalte, die zum Suchmuster «foo» passen, sondern nur den Namen
einer jeden Datei, deren Inhalt zum Suchmuster «foo» passt, aus. 
Und zwar spuckt «grep» jeden Dateinamen in einer eigenen Zeile aus,
genauer: «grep» spuckt die Zeichen des Dateinamens und anschließend
ein Newline‐Zeichen aus:

bar foo.txt
foo bar.txt
foo.txt
no bar.txt


Jetzt schau dir «xargs» an:  «xargs» liest einen Datenstrom aus
seinem Eingabekanal und zerlegt ihn nach gewissen Regeln in einzelne
Wörter.  Die Wörter sammelt er auf und, wenn er genug gesammelt hat,
startet er das ihm angegebene Programm und gibt ihm die Wörter als
Aufrufparameter mit.


Probiere das in Kombination mit «grep» wie oben aus:



grep -l -- foo *.txt | xargs -- printf 'Dateiname: %s\n'


Du erhältst das folgende Ergebnis:


Dateiname: bar
Dateiname: foo.txt
Dateiname: foo
Dateiname: bar.txt
Dateiname: foo.txt
Dateiname: no
Dateiname: bar.txt

Die Dateinamen, die «grep» (wie oben) zeilenweise geliefert hat,
werden von «xargs» dort, wo Leerzeichen in ihnen enthalten sind,
zerbrochen.  Das kommt von den «gewissen Regeln», nach den «xargs»
seinen Eingabedatenstrom zersägt.

So etwas ist natürlich bei Dateinamen inakzeptabel, wenn man die
anschließend noch weiterverwenden will.

Um das Problem zu beheben, kommen die GNU‐«grep»‐Option «-Z» und die
GNU‐«xargs»‐Option «-0» ins Spiel:

Die «grep»‐Option «-Z» befiehlt «grep», die Dateinamen bei der
Ausgabe nicht mit Newline‐ sondern mit NUL‐Zeichen zu trennen.  Das
NUL‐Zeichen ist das einzige Zeichen, das bereits vom Betriebssystem
her in Dateinamen nicht vorkommen kann.  Es ist das einzige Zeichen,
das sich für die Trennung von Dateinamen in einem Datenstrom eignet.

Die «xargs»‐Option «-0» befiehlt «xargs», seinen Eingabedatenstrom
nicht mehr nach den «gewissen Regeln» in Einzelteile zu zersägen,
sondern die Säge nur noch an den Stellen im Eingabedatenstrom, an
denen ein NUL‐Zeichen sitzt, anzusetzen.

Die «grep»‐Option «-Z» und die «xargs»‐Option «-0» sind (wie)
geschaffen für einander.  Probiere das folgende Kommando aus:

grep -lZ -- foo *.txt | xargs -0 -- printf 'Dateiname: %s\n'


Man erhält die folgende Ausgabe:  Die Dateinamen sind nicht
zerbrochen:  Jeder steht unverletzt in einer eigenen Zeile da.

Dateiname: bar foo.txt
Dateiname: foo bar.txt
Dateiname: foo.txt
Dateiname: no bar.txt


Langer Rede kurzer Sinn:  Wenn man die «grep»‐Option «-Z» und die
«xargs»‐Option «-0» zur Verfügung hat, verwendet man sie, wenn man
von «grep» ausgespuckte Dateinamen an «xargs» verfüttern will.

Um es vollends sicher zu machen, gibt man «xargs» noch die Option
«-r».  Sie bewirkt, dass «xargs» darauf verzichtet, das ihm
angegebene Programm zu starten, wenn im Eingabedatenstrom überhaupt
keine Daten ankommen.  Das ist ja beispielsweise beim Kommando

grep -lZ -- foobar *.txt | xargs -0 -- printf 'Dateiname: %s\n'

der Fall.  Ohne «-r» startet «xargs» das Programm «printf» trotzdem
ein einziges Mal ohne einen Dateinamenparameter, obwohl es richtig
wäre, es gar nicht zu starten.  Das Ergebnis ist, dass «printf» eine
Zeile ohne Dateinamen ausgibt, obwohl gar keine Ausgabe sinnvoller
wäre:

Dateiname:


Deshalb empfiehlt es sich,


grep -lZ -- foobar *.txt | xargs -0r -- printf 'Dateiname: %s\n'

zu verwenden.  Dann wird überhaupt nichts ausgegeben.


>Ich habe mich die letzten Monate intensiv mit R auseinandergesetzt,
>dort kann man (mit tidyverse) simpelste Ketten bilden. Aber dabei
>werden faktisch immer Vektoren übergeben, formal also immer
>dasselbe. Möglicherweise resultiert meine Verwirrung daher.

Mit R kenne ich mich nicht aus, kann dir daher nicht sagen, ob und
wo es da Vergleichbares gibt.

>
>> Wenn du ein «xargs» aus einem Pipe fütterst und damit
>> «(pdf‐)grep» startest, liest «xargs» Daten aus dem Pipe (in
>> deinem Anwendungsfall: Dateinamen) und startet damit «(pdf‐)grep»
>> mit den Dateinamen als Parametern.  Das tut «xargs» allerdings
>> nur dann zuverlässig, wenn du, wie Tim und Christian dir
>> nahegelegt haben, bei «(pdf‐)grep» die Optionen «-l» und «-Z» und
>> bei «xargs» die Optionen «-0» und «-r» verwendest.
>
>Die Zusatzoptionen habe ich auf Anhieb nicht ohne Syntaxfehler zum
>Laufen gebracht, aber das muss ich gelegentlich in Ruhe anschauen.

Schau das Beispiel oben an.  Da gibt es eigentlich nicht viel falsch
zu machen:  Im «grep»‐Handbuch wird dieser Anwendungsfall sogar
ausdrücklich erwähnt:

`-Z'
`--null'
Output a zero byte (the ASCII `NUL' character) instead of
the character that normally follows a file name. For
example, `grep -lZ' outputs a zero byte after each file name
instead of the usual newline. This option makes the output
unambiguous, even in the presence of file names containing
unusual characters like newlines. This option can be used
with commands like `find -print0', `perl -0', `sort -z', and
`xargs -0' to process arbitrary file names, even those that
contain newline characters.

Nochmal auf Deutsch zusammengefasst:  Wenn «grep» Dateinamen der
Dateien, die es durchsucht hat, zur Weiterverarbeitung ausspucken
soll (die Option «-l»), gib ihm die Option «-Z» dazu.  Wenn «find»
Dateinamen zur Weiterverarbeitung ausspucken soll, verwende bei
«find» das Prädikat «-print0».  Wenn «perl» Dateinamen aus seinem
Eingabekanal lesen und verarbeiten soll, gib ihm die Option «-0». 
Wenn «sort» Dateinamen aus seinem Eingabekanal lesen und sortieren
soll, gib ihm die Option «-z».  Wenn «xargs» Dateinamen aus seinem
Eingabekanal lesen und verwenden soll, gib ihm die Option «-0».

>> Lies ein gutes Buch über die Funktionsweise bzw. die
>> Systemaufruf‐Schnittstelle (hier speziell die Systemaufrufe
>> «pipe», «fork» und «execve») von Unix oder Linux.
>
>Ich bin für konkrete Literaturtipps dankbar. Die Fülle an
>Unix-Büchern jeglichen Jahrgangs in den hiesigen Bibliotheken ist
>unüberschaubar.

Ich habe mal das Buch von Maurice J. Bach: «The Design of the UNIX
Operating System» (von 1986) gelesen.  Es soll auch eine Fassung auf
Deutsch (ich meine, mit dem Titel «UNIX – Wie funktioniert das
Betriebssystem?») geben.

Natürlich ist es nicht mehr aktuell, d. h., zu Unix oder Linux ist
inzwischen viel Neues hinzugekommen.  Und sicher gibt es inzwischen
neuere Bücher.  Aber seit dem weiß ich, warum ich vor hard links,
file descriptor redirections, Dateinamen, Aufrufparametern,
Shell‐Kommandozeilen, login shells … keine Angst haben muss.

Tim Landscheidt

unread,
Jun 8, 2022, 12:34:27 AM6/8/22
to
Patrick Rudin <tax...@gmx.ch> wrote:

>>> Das ist aber ein "or", alle Beispiele hier im Thread gehen aber von
>>> einem "and" aus.

>>> Wenn ich das richtig verstanden habe, ist das mit Regexp keineswegs
>>> trivial umzusetzen:
>> Trivial nicht, aber auch nicht schwierig:
>> grep -E '(foo.*bar)|(bar.*foo)' *.txt

> Das sind aber erweiterte Regexp, die pdfgrep leider nicht
> zur Verfügung stehen...

Das müssten sie aber, wenn man die Option „--perl-regexp“
verwendet (ungetestet).

Tim

Peter Heitzer

unread,
Jun 8, 2022, 4:23:42 AM6/8/22
to
Patrick Rudin <tax...@gmx.ch> wrote:
>Peter Heitzer wrote:
>> Oder gleich ein grep verwenden, das Regexes beherrscht.
>> $ grep -E "foo|bar" *.txt
>> bei Gnu grep

>Das ist aber ein "or", alle Beispiele hier im Thread gehen aber von
>einem "and" aus.

Hast Recht. Man könnte es mit "(.*foo.*bar)|(.*bar.*foo)" machen, aber das
funktioniert nur, wenn "foo" und "bar" in der selben Zeile stehen.
Wenn die zu suchenden Strings in unterschiedlichen Zeilen stehen, geht es nur
mit Pipes.

Helmut Waitzmann

unread,
Jun 8, 2022, 6:50:39 AM6/8/22
to
Patrick Rudin <tax...@gmx.ch>:
Bist du dir bei dem bei dir installierten «pdfgrep» sicher?  Debian
Bullseye's und Buster's «pdfgrep» stehen laut Manual‐Page Erweiterte
Reguläre Ausdrücke zur Verfügung.  Übereinstimmendes Zitat aus
<https://manpages.debian.org/buster/pdfgrep/pdfgrep.1.en.html> und
<https://manpages.debian.org/bullseye/pdfgrep/pdfgrep.1.en.html>:

DESCRIPTION

Search for PATTERN in each PDF FILE and print matching
lines. By default, PATTERN is an extended regular
expression.


Nochmal zitiert:


>> grep -E '(foo.*bar)|(bar.*foo)' *.txt
>
>Das sind aber erweiterte Regexp, die pdfgrep leider nicht zur
>Verfügung stehen...

Gesetzt den Fall, «pdfgrep» böte wirklich nur Grundlegende Reguläre
Ausdrücke an, käme man auch ohne Erweiterte Reguläre Ausdrücke ans
Ziel, indem man die Fähigkeit von pdfgrep nutzte, mehrere Reguläre
Ausdrücke anzugeben:

pdfgrep -e 'foo.*bar' -e 'bar.*foo' -- *.txt

Patrick Rudin

unread,
Jun 8, 2022, 7:55:56 AM6/8/22
to
Helmut Waitzmann wrote:
> Gesetzt den Fall, «pdfgrep» böte wirklich nur Grundlegende Reguläre
> Ausdrücke an, käme man auch ohne Erweiterte Reguläre Ausdrücke ans Ziel,
> indem man die Fähigkeit von pdfgrep nutzte, mehrere Reguläre Ausdrücke
> anzugeben:
>
>   pdfgrep -e 'foo.*bar' -e 'bar.*foo' -- *.txt

Vermutlich habe ich einen falschen Schluss gezogen, weil er mit der
vorher genannten Syntax Dokumente nicht gefunden hat, die er hätte
finden müssen.

Diese von Dir genannte Version (mit pdf allerdings) funktioniert
teilweise. Nach vielen Versuchen mein Fazit: Es funktioniert nur, wenn
die Begriffe auf derselben Seite im pdf stehen. Stehen sie auf
unterschiedlichen Seiten, gibt es keinen Treffer.

Die Pipe-Variante funktioniert hingegen auch bei auf mehreren Seiten
verteilten Begriffen. Da sie auch einfacher zu tippen ist, genügt mir das.

Rein akademisch wäre es natürlich interessant, ob es eine
pdfgrep-Variante gibt, die mit einem Ausdruck die Kombination von zwei
Begriffen findet, die irgendwo im Dokument vorkommen...


Gruss

Patrick

Helmut Waitzmann

unread,
Jun 8, 2022, 10:36:12 AM6/8/22
to
Patrick Rudin <tax...@gmx.ch>:
>Helmut Waitzmann wrote:

>>   pdfgrep -e 'foo.*bar' -e 'bar.*foo' -- *.txt
>
>Vermutlich habe ich einen falschen Schluss gezogen, weil er mit der
>vorher genannten Syntax Dokumente nicht gefunden hat, die er hätte
>finden müssen.
>
>Diese von Dir genannte Version (mit pdf allerdings)
>

Ja, natürlich, du hast recht.  Es müssen PDF‐Dateien sein.  Mein
Fehler.

>funktioniert teilweise. Nach vielen Versuchen mein Fazit: Es
>funktioniert nur, wenn die Begriffe auf derselben Seite im pdf
>stehen. Stehen sie auf unterschiedlichen Seiten, gibt es keinen
>Treffer.

Genau.  «foo.*bar» ist ein regulärer Ausdruck, der passt, wenn «foo»
vor «bar» kommt und zwischen «foo» und «bar» beliebig viele
beliebige Zeichen liegen.

Bei «grep» passt der «.» im regulären Ausdruck auf einen
Zeilenwechsel nicht. => «bar» muss also innerhalb derselben Zeile
«foo» folgen.

Wie es bei «pdfgrep» aussieht, weiß ich nicht.  Möglicherweise passt
der «.» dort auch auf einen Zeilenwechsel, aber nicht auf
Seitenwechsel.  Das passt dann zu deiner Beobachtung.

>Die Pipe-Variante funktioniert hingegen auch bei auf mehreren
>Seiten verteilten Begriffen. Da sie auch einfacher zu tippen ist,
>genügt mir das.

Genau.  Finde alle Dokumente, die sowohl «foo» als auch «bar»
enthalten:

pdfgrep -lZ -- foo *.pdf |
xargs -0r -- pdfgrep -l -- bar

gibt die Namen – jeden in einer einzelnen Zeile – aller Dateien, die
sowohl «foo» als auch «bar» enthalten, aus.  Falls man mit den Namen
etwas anderes anstellen will, als sie nur auf dem Bildschirm zu
sehen, könnte man natürlich wieder mit der Option «-Z» und «xargs
-0r» fortfahren:

pdfgrep -lZ -- foo *.pdf |
xargs -0r -- pdfgrep -lZ -- bar |
xargs -0r -- …

>Rein akademisch wäre es natürlich interessant, ob es eine
>pdfgrep-Variante gibt, die mit einem Ausdruck die Kombination von zwei
>Begriffen findet, die irgendwo im Dokument vorkommen...

Das müsste eine Variante sein, bei der sich Treffer für einen
regulären Ausdruck über das ganze Dokument erstrecken dürfen, oder
anders ausgedrückt, bei der der «.» im regulären Ausdruck auch auf
einen Zeilen‐ oder Seitenwechsel passt.  Vielleicht ist es mit der
Option «--perl-regexp» machbar?

Patrick Rudin

unread,
Jun 8, 2022, 3:00:26 PM6/8/22
to
Helmut Waitzmann wrote:
> (
> set -- foo bar &&
> for muster
> do
> printf '%s\n' "$1" > "$1".txt
> printf '%s\n' "$1" > "no $2".txt
> printf '%s\n' "${1} ${2}" > "${1} ${2}".txt
> set -- "$@" "$1"
> shift
> done
> )

Danke für die Beispiele. Indes: Auf meinem Rechner gibt es keine
Dateinamen mit Leerzeichen. Falls nötig, verwende ich Unterstriche. Und
wer Newlines in Dateinamen verwendet, gehört gefedert.

> Deshalb empfiehlt es sich,
>
>
> grep -lZ -- foobar *.txt | xargs -0r -- printf 'Dateiname: %s\n'
>
> zu verwenden.  Dann wird überhaupt nichts ausgegeben.

Wenn ich hinten Evince aufrufe, öffnet der sich bei mangelndem Input
einfach mit eine Fenster der letzten paar verwendeten Dateien. Nicht so
wild.

> Mit R kenne ich mich nicht aus, kann dir daher nicht sagen, ob und
> wo es da Vergleichbares gibt.

Es ist dort eine sehr simple Möglichkeit, verschiedene Befehle (ohne
unübersichtliches Zwischenspeichern) in gut lesbarer Weise
aneinanderzuhängen.

https://dplyr.tidyverse.org/articles/dplyr.html#combining-functions-with

> Ich habe mal das Buch von Maurice J. Bach: «The Design of the UNIX
> Operating System» (von 1986) gelesen.  Es soll auch eine Fassung auf
> Deutsch (ich meine, mit dem Titel «UNIX – Wie funktioniert das
> Betriebssystem?») geben.

Hm, ja, eine der hiesigen Bibliotheken hat beide Versionen. Hab heute
kurz reingeschaut, leider miserabel geschrieben, kaum Beispiele, für
mich ist das nichts...


Gruss

Patrick

Helmut Waitzmann

unread,
Jun 8, 2022, 7:11:45 PM6/8/22
to
Patrick Rudin <tax...@gmx.ch>:

>Auf meinem Rechner gibt es keine Dateinamen mit Leerzeichen.
>

Bist du sicher?  Hast du deinen Rechner komplett nach Dateinamen mit
besonderen Zeichen durchsucht und nichts gefunden?  Ich habe mal
mein HOME‐Verzeichnis nach Dateinamen, die solche Zeichen enthalten,
durchforstet und habe Dateinamen gefunden, in denen ein
installiertes Programm seinen Zustand speichert und auf deren Namen
ich keinen Einfluss habe.

>Falls nötig, verwende ich Unterstriche.
>

Du schon.  Aber kannst du die Hand dafür ins Feuer legen, dass
keines der Programme, die du verwendest, vielleicht irgendwo in
Konfigurations‐ oder Laufzeit‐Daten Dateinamen mit besonderen
Zeichen verwendet?

Um das zu garantieren, müsstest du ein Betriebssystem verwenden, bei
dem von vorne herein besondere Zeichen in Dateinamen nicht enthalten
sein können.

>Und wer Newlines in Dateinamen verwendet, gehört gefedert.
>

Dieses Urteil kannst du natürlich sprechen, nur wird es weder die
von dir zwar eingesetzten, aber nicht von dir selbst entwickelten
Programme, noch deren Entwickler, stören.

Sofern du dann Programme – etwa Shell‐Skripte – schreibst, die sich
an keinen Dateinamen auf deinem System verschlucken sollen, müssen
die Programme so geschrieben sein, dass sie mit Dateinamen mit
besonderen Zeichen zurecht kommen.  Sonst kann es passieren, dass
sie Schaden anrichten, wenn sie über Dateinamen, mit denen sie nicht
rechnen, stolpern.

Hast du dich informiert, welche Zeichen in Dateinamen Ärger machen,
wenn man die Dateinamen an «xargs» ohne die Option «-0» verfüttert? 
(Tipp:  Es sind nicht nur Leerzeichen und Zeilenwechsel.)

Tim Landscheidt

unread,
Jun 9, 2022, 6:25:57 AM6/9/22
to
Patrick Rudin <tax...@gmx.ch> wrote:

>> (
>> set -- foo bar &&
>> for muster
>> do
>> printf '%s\n' "$1" > "$1".txt
>> printf '%s\n' "$1" > "no $2".txt
>> printf '%s\n' "${1} ${2}" > "${1} ${2}".txt
>> set -- "$@" "$1"
>> shift
>> done
>> )

> Danke für die Beispiele. Indes: Auf meinem Rechner gibt es
> keine Dateinamen mit Leerzeichen. Falls nötig, verwende ich
> Unterstriche. Und wer Newlines in Dateinamen verwendet,
> gehört gefedert.

> […]

In Deiner schönen Welt möchte ich auch leben :-). Das Pro-
blem ist nicht, dass Deine bestehenden Dateinamen Leerzei-
chen/Newlines enthalten, sondern dass Du eines Tages nicht
mehr daran denkst, dass Deine Dateinamen keine Leerzeichen/
Newlines enthalten dürfen, oder eine Datei aus einer exter-
nen Quelle erhältst, wo Dir nicht auffällt, dass der Name
Leerzeichen/Newlines enthält, oder ein Programm Dateinamen
mit Leerzeichen/Newlines erzeugt, weil es nicht weiß, dass
Du Dateinamen mit Leerzeichen/Newlines verbietest, oder ein
böser Hacker eine Datei erstellt, deren Namen Leerzeichen/
Newlines enthält, oder, oder, oder.

Wenn man sich angewöhnt, Dateinamen als Objekte, die jedes
Zeichen außer \0 enthalten können, zu betrachten, muss man
sich über solche Fragen keine Gedanken mehr verschwenden.

Tim

Patrick Rudin

unread,
Jun 9, 2022, 1:03:32 PM6/9/22
to
Helmut Waitzmann wrote:
> Patrick Rudin <tax...@gmx.ch>:
>
>> Auf meinem Rechner gibt es keine Dateinamen mit Leerzeichen.
>
> Bist du sicher?

Sagen wir mal so: Diese spezielle pdf-Sammlung, die ich mit pdfgrep
durchsuche, ist in dieser Hinsicht unproblematisch. Würde ich Skripte
schreiben, die das gesamte System durchsuchen, sähe es wohl anders aus.

>> Und wer Newlines in Dateinamen verwendet, gehört gefedert.
>
> Dieses Urteil kannst du natürlich sprechen, nur wird es weder die von
> dir zwar eingesetzten, aber nicht von dir selbst entwickelten Programme,
> noch deren Entwickler, stören.

Kannst Du ein Beispiel nennen, wo ein Programm Dateien schreibt, deren
Dateinamen ein Newline enthalten? Das wäre ja schon irgendwie krass...

> Hast du dich informiert, welche Zeichen in Dateinamen Ärger machen, wenn
> man die Dateinamen an «xargs» ohne die Option «-0» verfüttert? (Tipp:
> Es sind nicht nur Leerzeichen und Zeilenwechsel.)

Noch nicht. Vermutlich machen Umlaute Ärger, und in R sorgen auch mit
Ziffern beginnende Spaltennamen in einer Tabelle immer für viel Spass.

Mir ist schon klar, wieviel Müll in der Welt rumschwimmt. Es gibt
csv-Dateien, die im Datumsfeld jeweils "Januar 2020", "Februar 2020",
"März 2020" und so weiter liefern, und manche Leute glauben, das sei
tatsächlich ein maschinenlesbares Format.



Gruss

Patrick

Bernd Mayer

unread,
Jun 9, 2022, 4:01:23 PM6/9/22
to
Am 09.06.22 um 19:03 schrieb Patrick Rudin:
> Helmut Waitzmann wrote:
>> Patrick Rudin <tax...@gmx.ch>:
>>
>>> Auf meinem Rechner gibt es keine Dateinamen mit Leerzeichen.
>>
> Mir ist schon klar, wieviel Müll in der Welt rumschwimmt. Es gibt
> csv-Dateien, die im Datumsfeld jeweils "Januar 2020", "Februar 2020",
> "März 2020" und so weiter liefern, und manche Leute glauben, das sei
> tatsächlich ein maschinenlesbares Format.
>
Hallo,

ich hatte mir schonmal mit detox geholfen zum Bereinigen von störenden
Sonderzeichen in Dateinamen unter Linux:

https://www.heise.de/ratgeber/Dateinamen-bereinigen-mit-dem-Linux-Tool-Detox-5043029.html

https://linux.die.net/man/1/detox

http://detox.sourceforge.net/


Bernd Mayer

Helmut Waitzmann

unread,
Jun 9, 2022, 7:26:09 PM6/9/22
to
Patrick Rudin <tax...@gmx.ch>:
>Helmut Waitzmann wrote:
>> Patrick Rudin <tax...@gmx.ch>:
>>
>>> Auf meinem Rechner gibt es keine Dateinamen mit Leerzeichen.
>>>
>>
>> Bist du sicher?
>>
>
>Sagen wir mal so: Diese spezielle pdf-Sammlung, die ich mit pdfgrep
>durchsuche, ist in dieser Hinsicht unproblematisch. Würde ich
>Skripte schreiben, die das gesamte System durchsuchen, sähe es wohl
>anders aus.

Solang du das bei der Anwendung des Skripts in Erinnerung behältst,
geht es in Ordnung.  (Ich brauche beispielsweise Skripte, die mein
ganzes HOME‐Verzeichnis durchsuchen.)

>>> Und wer Newlines in Dateinamen verwendet, gehört gefedert.
>>>
>>
>> Dieses Urteil kannst du natürlich sprechen, nur wird es weder die
>> von dir zwar eingesetzten, aber nicht von dir selbst entwickelten
>> Programme, noch deren Entwickler, stören.
>
>Kannst Du ein Beispiel nennen, wo ein Programm Dateien schreibt, deren
>Dateinamen ein Newline enthalten? Das wäre ja schon irgendwie krass...

Für Newline‐Zeichen ist mir bisher noch kein Beispiel begegnet, für
andere Zeichen aber schon; und ich habe halt keine Garantie, dass
das auch so bleibt.

>> Hast du dich informiert, welche Zeichen in Dateinamen Ärger machen,
>> wenn man die Dateinamen an «xargs» ohne die Option «-0» verfüttert?
>> (Tipp: Es sind nicht nur Leerzeichen und Zeilenwechsel.)
>
>Noch nicht. Vermutlich machen Umlaute Ärger
>

Wenn die Programme (Shell u. a.), die mit den Dateinamen arbeiten
müssen, 8‐bit‐clean sind, erwarte ich da (zumindest im Locale
«POSIX») eher keinen Ärger mit Zeichen, deren Kodierung zu Bytes mit
Werten zwischen 128 und 255 führt.  Den sehe ich eher bei «xargs»: 
Ohne die Option «-0» haben nicht nur Leerstellen und Zeilenwechsel
sondern noch weitere Zeichen im ASCII‐Zeichensatz (zwischen den
Code‐Positionen 33 und 126, also ganz normale druckbare Zeichen)
eine Sonderbedeutung.

>Mir ist schon klar, wieviel Müll in der Welt rumschwimmt.
>

Drum bin ich froh, dass GNU‐«xargs» die Option «-0» und GNU‐«find»,
‐«sort», ‐«grep» und ‐«tar» entsprechende passende Optionen kennen.


Damit kann man dann beispielsweise mit dem Kommando


find … -print0 |
sort -z … |
xargs -0r …

eine riesige Menge an Dateinamen problemlos sortiert verarbeiten,
während man ansonsten mit

find … -exec my_quote_words_for_escaped_nl '{}' + |
sort … |
my_escaped_nl_to_xargs |
xargs …

ankommen müsste, wobei «my_quote_words_for_escaped_nl» ein
Dateinamensumformer ist, der jeden übergebenen Dateinamen so
newline‐umkodiert ausgibt, dass beim anschließenden zeilenweisen
Sortieren die Dateinamen nicht mehr zerbrechen.

«my_escaped_nl_to_xargs» formt dann die umkodierten Zeilen so um,
dass das Ergebnis, auf «xargs» losgelassen, «xargs» die originalen
Dateinamen gewinnen lässt.

Das Problem dabei:  Sowohl «my_quote_words_for_escaped_nl» als auch
«my_escaped_nl_to_xargs» muss man selber entwickeln, und ob man beim
Sortieren der newline‐kodierten Zeilen die gewünschte Sortierung
wirklich hinbekommt, ist auch noch nicht geklärt.

Hermann Riemann

unread,
Jun 10, 2022, 1:06:16 AM6/10/22
to
Am 09.06.22 um 00:39 schrieb Helmut Waitzmann:
> Patrick Rudin <tax...@gmx.ch>:
>
>> Auf meinem Rechner gibt es keine Dateinamen mit Leerzeichen.
>
> Bist du sicher?  Hast du deinen Rechner komplett nach Dateinamen mit
> besonderen Zeichen durchsucht und nichts gefunden?  Ich habe mal mein
> HOME‐Verzeichnis nach Dateinamen, die solche Zeichen enthalten,
> durchforstet und habe Dateinamen gefunden, in denen ein installiertes
> Programm seinen Zustand speichert und auf deren Namen ich keinen
> Einfluss habe.

Zu Unix gehört IMHO auch C
Und das C Laufzeitsystem kann bei Datei (und Verzeichnis) Namen
alle Hexwerte ( auch ISO statt utf8) außer '/' und '\0'.
( Bei letzteren wird Umbenennung aufwendig. )

>> Falls nötig, verwende ich Unterstriche.

> Du schon.  Aber kannst du die Hand dafür ins Feuer legen, dass keines
> der Programme, die du verwendest, vielleicht irgendwo in Konfigurations‐
> oder Laufzeit‐Daten Dateinamen mit besonderen Zeichen verwendet?

Ich habe ein kleines ( in Python3 geschriebenes) script,
welches rekursiv in Ordner die Umbennung von blank nach underline macht.
Aus windows Quellen kommen ja dauernd solche Namen an.

> Um das zu garantieren, müsstest du ein Betriebssystem verwenden, bei dem
> von vorne herein besondere Zeichen in Dateinamen nicht enthalten sein
> können.

Selber schreiben?
Da dürfte ein Hintergrund Programm, welches permanent
Dateinamen derart ändert, leichter zu programmieren sein.
Das RAM könnte dann bald mit Dateinamen gefüllt sein,
und die CPU würde gerne schwitzen.

>> Und wer Newlines in Dateinamen verwendet, gehört gefedert.

Auch bei '\' für windows Liebhaber?

--
http://www.hermann-riemann.de

Ulli Horlacher

unread,
Jun 10, 2022, 2:30:35 AM6/10/22
to
Helmut Waitzmann <nn.th...@xoxy.net> wrote:

> >Kannst Du ein Beispiel nennen, wo ein Programm Dateien schreibt, deren
> >Dateinamen ein Newline enthalten? Das wäre ja schon irgendwie krass...
>
> Für Newline?Zeichen ist mir bisher noch kein Beispiel begegnet

Mir mehrfach. Das waren Files aus (zip-)Archive, die ich von Macianern
bekommen habe.

--
Ullrich Horlacher Server und Virtualisierung
Rechenzentrum TIK
Universitaet Stuttgart E-Mail: horl...@tik.uni-stuttgart.de
Allmandring 30a Tel: ++49-711-68565868
70569 Stuttgart (Germany) WWW: http://www.tik.uni-stuttgart.de/

Gerald E¡scher

unread,
Jun 10, 2022, 11:10:22 AM6/10/22
to
Ulli Horlacher schrieb am 10/6/2022 08:30:

> Helmut Waitzmann <nn.th...@xoxy.net> wrote:
>
>> >Kannst Du ein Beispiel nennen, wo ein Programm Dateien schreibt, deren
>> >Dateinamen ein Newline enthalten? Das wäre ja schon irgendwie krass...
>>
>> Für Newline?Zeichen ist mir bisher noch kein Beispiel begegnet
>
> Mir mehrfach. Das waren Files aus (zip-)Archive, die ich von Macianern
> bekommen habe.

Wann war das? Vor rund 20 Jahren unter klassischem MacOS? Im
üblichen Datei-Speichern-Dialog von aktuellem macOS (POSIX-konformes
Unix!) ist es mir nicht gelungen, einen Dateinamen mit Newline zu
erzeugen.
Im Terminal mit bash geht es, aber von dessen Existenz wissen
durchschnittliche Mac-Luser nicht einmal.

$ touch testdatei
$ mv testdatei "test
> datei"
$ ls test*
test?datei

--
Gerald

Helmut Waitzmann

unread,
Jun 10, 2022, 4:05:00 PM6/10/22
to
Hermann Riemann <nosp...@hermann-riemann.de>:
>Am 09.06.22 um 00:39 schrieb Helmut Waitzmann:
>> Patrick Rudin <tax...@gmx.ch>:

[Es geht um Dateinamen, die Leerzeichen enthalten.]


>> Ich habe mal mein HOME‐Verzeichnis nach Dateinamen, die solche
>> Zeichen enthalten, durchforstet und habe Dateinamen gefunden, in
>> denen ein installiertes Programm seinen Zustand speichert und auf
>> deren Namen ich keinen Einfluss habe.

[…]

>>> Falls nötig, verwende ich Unterstriche.
>>>
>
>> Du schon.  Aber kannst du die Hand dafür ins Feuer legen, dass
>> keines der Programme, die du verwendest, vielleicht irgendwo in
>> Konfigurations‐ oder Laufzeit‐Daten Dateinamen mit besonderen
>> Zeichen verwendet?
>>
>> Um das zu garantieren, müsstest du ein Betriebssystem verwenden,
>> bei dem von vorne herein besondere Zeichen in Dateinamen nicht
>> enthalten sein können.
>
>Da dürfte ein Hintergrund Programm, welches permanent
>Dateinamen derart ändert, leichter zu programmieren sein.

Aber es greift zu kurz:  Der Kontext – oben noch zu lesen – war ein
Programm, das seinen Zustand in Dateinamen, die Leerzeichen
enthalten und auf die ich als Anwender des Programms keinen Einfluss
habe, speichert.  Wenn man dem die Dateien unter dem Hintern
umbenennt, wird es sie erstens nicht mehr finden und zweitens neue
mit Leerstellen im Namen anlegen.

Du bist in ‚bester‘ Usenet‐Tradition:  Wenn die Diskussion an den
Zielpunkt angekommen ist (hier:  Als Anwender hat man nicht die
Macht, zu verhindern, dass Leerzeichen in Dateinamen auftauchen, und
deshalb muss man immer damit rechnen, dass Leerzeichen in Dateinamen
enthalten sein können.), dann kommt einer daher, ignoriert die in
der Diskussion bereits erarbeiteten Fakten und dreht eine neue
Runde.

Warum liest du die vorhandenen Diskussionsbeiträge nicht
sorgfältig – oder soll ich lieber schreiben: vorsichtig, denn es
könnte ja notwendig werden, nachzudenken –, ehe du in die Diskussion
einsteigst?

Crosspost & Followup-To: de.soc.usenet

Claus Reibenstein

unread,
Jun 20, 2022, 7:25:01 AM6/20/22
to
Patrick Rudin schrieb am 06.06.2022 um 17:14:
> Tim Landscheidt wrote:
>> | pdfgrep -Z -l blabla verzeichnis/*.pdf | xargs -0r evince
>
> Ah, xargs, danke.
>
> Ich hab keine Leerzeichen in den Dateinamen, daher tut es ein
> pdfgrep -il blabla verzeichnis/*.pdf | xargs evince
>
> perfekt, bei mehreren Treffern macht er so mehrere Fenster auf.

Wenn es nicht zu viele Treffer sind, sollte das auch so funktionieren:

evince $(pdfgrep -il blabla verzeichnis/*.pdf)

Oder so:

evince `pdfgrep -il blabla verzeichnis/*.pdf`

Gruß
Claus
0 new messages