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

grep: Die Argumentliste ist zu lang

665 views
Skip to first unread message

Christopher Brosch

unread,
Jul 11, 2000, 3:00:00 AM7/11/00
to
Guten Morgen,

wenn ich Verzeichnisse mit vielen Dateien (einige 1000) mit grep
durchsuche, bekomme ich ab einer bestimmten Anzahl an Dateien in diesem
Verzeichnis (~2800 funktioniert noch, ~11000 nicht mehr) folgende
Fehlermeldung (ja, ich benutze ein überestztes Suse-Linux ;-):

/usr/bin/grep: Die Argumentliste ist zu lang

Ähnliches passiert bei zip. Gibt es Möglichkeiten, diese Beschränkungen
zu umgehen? Gibt es irgendwo eine "aufgebohrte" Version von grep oder
zip?

Bis dann,

Christopher

Daniel Engelschalt

unread,
Jul 11, 2000, 3:00:00 AM7/11/00
to
Christopher Brosch schrieb:

>
> Guten Morgen,
>
> wenn ich Verzeichnisse mit vielen Dateien (einige 1000) mit grep
> durchsuche, bekomme ich ab einer bestimmten Anzahl an Dateien in diesem
> Verzeichnis (~2800 funktioniert noch, ~11000 nicht mehr) folgende
> Fehlermeldung (ja, ich benutze ein überestztes Suse-Linux ;-):
>
> /usr/bin/grep: Die Argumentliste ist zu lang
Versuche einfach
find . -name "*" -exec [Befehl] {} \;
^-- wird durch den "gefundenen"
Dateinamen ersetzt

Daniel

Christian Stieber

unread,
Jul 11, 2000, 3:00:00 AM7/11/00
to
Christopher Brosch <po...@christopherbrosch.de> wrote:

> /usr/bin/grep: Die Argumentliste ist zu lang
>

> Ähnliches passiert bei zip. Gibt es Möglichkeiten, diese Beschränkungen
> zu umgehen? Gibt es irgendwo eine "aufgebohrte" Version von grep oder
> zip?

Das ist eine künstliche Beschränkung die nicht von grep oder zip zu
verantworten ist --- das Limit ist im Kernel. Das ist eine der vielen
Stellen wo aufgrund programmiertechnischer Faulheit das übliche "es
gab dieses Limit schon immer, also lassen wir es" zum Einsatz kommt...

Christian


--
About the design flaws of Linux:
I still maintain the point that designing a monolithic kernel in 1991 is a
fundamental error. Be thankful you are not my student. You would not get
a high grade for such a design. (Andrew Tanenbaum to Linus Torvalds)

Cornelius Krasel

unread,
Jul 11, 2000, 3:00:00 AM7/11/00
to
Christopher Brosch <po...@christopherbrosch.de> wrote:
> wenn ich Verzeichnisse mit vielen Dateien (einige 1000) mit grep
> durchsuche, bekomme ich ab einer bestimmten Anzahl an Dateien in diesem
> Verzeichnis (~2800 funktioniert noch, ~11000 nicht mehr) folgende
> Fehlermeldung (ja, ich benutze ein überestztes Suse-Linux ;-):
>
> /usr/bin/grep: Die Argumentliste ist zu lang
>
> Ähnliches passiert bei zip. Gibt es Möglichkeiten, diese Beschränkungen
> zu umgehen? Gibt es irgendwo eine "aufgebohrte" Version von grep oder
> zip?

Die Begrenzung stammt vermutlich nicht von grep, sondern von der bash.

Du kannst das Problem wahrscheinlich mit einer Kombination aus find,
xargs und grep erschlagen.

find . -type f -maxdepth 1 -print | xargs grep expr

Die Variante

find . -type f -maxdepth 1 -exec grep expr '{}' \;

ist ebenfalls moeglich, aber nicht so guenstig, weil fuer jedes File
ein separater grep-Prozess aufgerufen wird.

--Cornelius.

--
/* Cornelius Krasel, U Wuerzburg, Dept. of Pharmacology, Versbacher Str. 9 */
/* D-97078 Wuerzburg, Germany email: pha...@rzbox.uni-wuerzburg.de SP4 */
/* "Science is the game we play with God to find out what His rules are." */

Christopher Brosch

unread,
Jul 11, 2000, 3:00:00 AM7/11/00
to
Cornelius Krasel schrieb :

>> [..] Gibt es Möglichkeiten, diese Beschränkungen


>> zu umgehen? Gibt es irgendwo eine "aufgebohrte" Version von grep oder
>> zip?

[..]

>Du kannst das Problem wahrscheinlich mit einer Kombination aus find,
>xargs und grep erschlagen.
>
>find . -type f -maxdepth 1 -print | xargs grep expr

Wenn ich an die Stelle des Punktes das zu durchsuchende Verzeichnis und
für expr den Ausdruck eingebe (sicherlich war das auch so gemeint ;-),
kann ich beliebig große Verzeichnisse durchsuchen - auch wenn dieser
Befehl bei kleinen Verzeichnissen um einiges langsamer ist als ein
einfaches "grep". Danke für den Hinweis.

Bis dann,

Christopher

Cornelius Krasel

unread,
Jul 11, 2000, 3:00:00 AM7/11/00
to
Christopher Brosch <po...@christopherbrosch.de> wrote:
> Cornelius Krasel schrieb :

>>Du kannst das Problem wahrscheinlich mit einer Kombination aus find,
>>xargs und grep erschlagen.
>>
>>find . -type f -maxdepth 1 -print | xargs grep expr
>
> Wenn ich an die Stelle des Punktes das zu durchsuchende Verzeichnis und
> für expr den Ausdruck eingebe (sicherlich war das auch so gemeint ;-),
> kann ich beliebig große Verzeichnisse durchsuchen - auch wenn dieser
> Befehl bei kleinen Verzeichnissen um einiges langsamer ist als ein
> einfaches "grep". Danke für den Hinweis.

Der Geschwindigkeitsverlust kommt unter anderem daher zustande, dass
zwei zusaetzliche Programme aufgerufen werden. Ausserdem muss "find"
fuer den "-type f" jeweils die ganze Inode auslesen und kann nicht
nur einfach das Directory-Listing herunterrattern kann. Falls Du keine
Directories in dem fraglichen Verzeichnis hast, bist Du daher unter
Umstaenden mit
find [dir] -maxdepth 1 -print | grep '/' | xargs grep [expr]
ein bisschen schneller. Mal schauen:

Variante 1: 0.190u 12.000s 3:08.88 6.4% 0+0k 0+0io 14196pf+0w

Variante 2: 0.320u 12.440s 2:44.04 7.7% 0+0k 0+0io 14264pf+0w

Jost Boekemeier

unread,
Jul 11, 2000, 3:00:00 AM7/11/00
to
po...@christopherbrosch.de (Christopher Brosch) writes:

> Verzeichnis (~2800 funktioniert noch, ~11000 nicht mehr) folgende

Unter Unix sind Verzeichnisse normale Dateien, wobei die
Directory-Datei eine aliste darstellt (aber kein hash zum
Beispiel). Daher ist die Verwaltung von mehr als 1000 Dateien in
einem Verzeichnis ineffizient.

Viele Tools stellen sich darauf ein und können keine endlos langen
Kommandozeilen verarbeiten. [Die Fehlermeldung stammt übrigens nicht
vom Kernel sondern von den Tools]


Jost

Jost Boekemeier

unread,
Jul 11, 2000, 3:00:00 AM7/11/00
to
po...@christopherbrosch.de (Christopher Brosch) writes:

> Cornelius Krasel schrieb :
>
> >> [..] Gibt es Möglichkeiten, diese Beschränkungen
> >> zu umgehen? Gibt es irgendwo eine "aufgebohrte" Version von grep oder
> >> zip?
>
> [..]
>

> >Du kannst das Problem wahrscheinlich mit einer Kombination aus find,
> >xargs und grep erschlagen.
> >
> >find . -type f -maxdepth 1 -print | xargs grep expr

^^^^^^^^^^^


>
> Wenn ich an die Stelle des Punktes das zu durchsuchende Verzeichnis und
> für expr den Ausdruck eingebe (sicherlich war das auch so gemeint ;-),

Hoffentlich nicht, das waere naemlich durch die Brust ins Auge. :)


echo <dateinamen> | xargs grep expr

Da echo ein eingebautes Kommando der Shell ist, akzeptiert
echo eine "unendlich" lange Kommandozeile.

Jost

Matthias Warkus

unread,
Jul 11, 2000, 3:00:00 AM7/11/00
to
It was the 11 Jul 2000 18:06:23 +0200...

...and Jost Boekemeier <jost...@calvados.zrz.tu-berlin.de> wrote:
> po...@christopherbrosch.de (Christopher Brosch) writes:
>
> > Verzeichnis (~2800 funktioniert noch, ~11000 nicht mehr) folgende
>
> Unter Unix sind Verzeichnisse normale Dateien, wobei die
> Directory-Datei eine aliste darstellt (aber kein hash zum
> Beispiel).

Jetzt würde ich mal gerne wissen, wie das beim reiserfs ist...

mawa
--
Mix the gin and vermouth in a shaker with ice. Strain the ice out of
the drink as you pour it into a glass. Place one or two olives into
the glass. Drink. Repeat.
-- mlw on making Martinis

Juergen Ilse

unread,
Jul 11, 2000, 3:00:00 AM7/11/00
to
Hallo,

Jost Boekemeier <jost...@calvados.zrz.tu-berlin.de> wrote:
> po...@christopherbrosch.de (Christopher Brosch) writes:
>> Verzeichnis (~2800 funktioniert noch, ~11000 nicht mehr) folgende
> Unter Unix sind Verzeichnisse normale Dateien, wobei die
> Directory-Datei eine aliste darstellt (aber kein hash zum

> Beispiel). Daher ist die Verwaltung von mehr als 1000 Dateien in
> einem Verzeichnis ineffizient.

Wie weit das zutrifft, haengt ggfs. vom bverwendeten Filesystem, von
der verwendeten unix-Version sowie ggfs. noch von einigen anderen
Faktoren ab. in den meisten Faellen duerftest du aber recht haben.

> Viele Tools stellen sich darauf ein und können keine endlos langen
> Kommandozeilen verarbeiten. [Die Fehlermeldung stammt übrigens nicht
> vom Kernel sondern von den Tools]

Die Fehlermeldung soll demnach von grep kommen? Weit daneben...
Es gibt eine Maximallaenge der Kommandozeile, und die ist nicht (nur)
von der shell abhaengig, auch im Kernel gibt es diese Schranke (daher
gibt es auch fuer die Betriebssystemfunktion execve() den Returnwert
E2BIG falls die Argumentliste zu lang ist). Die Groesse der Schranke
findest du uebrigens in der Datei /usr/include/linux/limits.h ...
Bei Linux liegt demnach der Wert defaultmaessig bei 128kb, bei SunOS4.1
auf Sparc war die Grenze AFAIK deutlich groesser (moeglicherweise sogar
bei 4mb, ich meine da mal so etwas gelesen zu haben)...

Tschuess,
Juergen Ilse (il...@asys-h.de)
--
Alles auf dieser Erde geht natuerlich zu, | Juergen Ilse
nur meine Hose geht natuerlich NICHT zu... | Internet POP Hannover GmbH
--------------------------------------------------| Vahrenwalder Strasse 205
Neu in de.comp.os.linux.*? Lies die .infos-Gruppe | 30165 Hannover

Juergen Ilse

unread,
Jul 11, 2000, 3:00:00 AM7/11/00
to
Hallo,

Jost Boekemeier <jost...@calvados.zrz.tu-berlin.de> wrote:
> po...@christopherbrosch.de (Christopher Brosch) writes:

>> Cornelius Krasel schrieb :


>> >Du kannst das Problem wahrscheinlich mit einer Kombination aus find,
>> >xargs und grep erschlagen.
>> >
>> >find . -type f -maxdepth 1 -print | xargs grep expr
> ^^^^^^^^^^^
>>
>> Wenn ich an die Stelle des Punktes das zu durchsuchende Verzeichnis und
>> für expr den Ausdruck eingebe (sicherlich war das auch so gemeint ;-),
> Hoffentlich nicht, das waere naemlich durch die Brust ins Auge. :)

Das ist eine der wenigen wirklich allgemeingueltigen Loesungen.

> echo <dateinamen> | xargs grep expr

Muss nicht immer funktionieren.

> Da echo ein eingebautes Kommando der Shell ist, akzeptiert
> echo eine "unendlich" lange Kommandozeile.

Abgesehen davon, dass es auch in der shell eine Schranke fuer die
Maximallaenge der Argumentliste geben kann (du hast nicht gesagt,
welche shell du hier voraussetzt) ist noch nicht einmal die Aus-
sage unter allen Umstaenden richtig, es wuerde sich bei "echo" um
einen shell-internen Befehl handeln. Bei der bash ist echo ein
interner Befehl, bei der ksh ein alias auf den internen Befehl print
und bei der urspruenglichen Bourne-shell war es kein internes Kom-
mando (sondern ueblicherweise /bin/echo, was es auf nahezu allen
unix-Systemen immer noch gibt).

Anselm Lingnau

unread,
Jul 12, 2000, 3:00:00 AM7/12/00
to
Im Artikel <p2tg0pg...@ruebe.zrz.tu-berlin.de> schrieb
Jost Boekemeier <jost...@calvados.zrz.tu-berlin.de>:

> Viele Tools stellen sich darauf ein und können keine endlos langen
> Kommandozeilen verarbeiten. [Die Fehlermeldung stammt übrigens nicht
> vom Kernel sondern von den Tools]

Das ist falsch. Die maximale Länge der Kommandozeile ist eine
Eigenschaft des Kernels. Laut POSIX.1 müssen Kommandozeilen im
Gesamtwert von mindestens 4096 Bytes unterstützt werden (siehe
Konstante »_POSIX_ARG_MAX« im Header »/usr/include/limits.h«), aber
heutige Systeme lassen in der Regel wesentlich längere Kommandozeilen
zu. Man kann den aktuellen Wert mit einem Programm wie

#define _POSIX_SOURCE 1
#include <stdio.h>
#include <unistd.h>
#include <limits.h>
int
main (void)
{
printf("ARG_MAX = %lu\n", sysconf(_SC_ARG_MAX));
exit(0);
}

abfragen; auf meinem System (Linux 2.2.x) kommt dabei »131072« heraus.

Wenn man den Systemaufruf »execve(2)« mit einem zu langen
Argumentvektor aufruft, bekommt man den Fehlercode E2BIG zurück, und
zwar vom Kernel und nicht vom aufgerufenen Programm (siehe
Manpage). Dem aufgerufenen Programm kann es ja auch völlig egal sein,
wie groß seine Argumente sind; es bekommt einen »argv«-Vektor von
Zeigern und damit hat sich das.

Siehe hierzu auch Stevens, »Advanced Programming in the Unix
Environment«, Kap. 8.9 (insbes. S. 209 unten) sowie Kap. 2.5.4,
S. 35-39.

Anselm
--
Anselm Lingnau ......................... lin...@tm.informatik.uni-frankfurt.de
Happiness isn't something you experience; it's something you remember.
-- Oscar Levant

Christopher Brosch

unread,
Jul 12, 2000, 3:00:00 AM7/12/00
to
Jost Boekemeier schrieb :

>> >find . -type f -maxdepth 1 -print | xargs grep expr

[..]

>echo <dateinamen> | xargs grep expr

Der Befehl ist auf jeden Fall einfacher zu behalten als die anderen
beiden. Ich habe mal die Geschwindigkeit dieser drei Möglichkeiten
mittels time verglichen, interessanterweise braucht der kürzeste
Befehl am längsten für die gleiche Aufgabe:


chbrosch@brosch:~ > time find /var/spool/news/de/alt/fan/bluemchen/
-maxdepth 1 -print | grep '/' | xargs grep Blümchen

[..]

real 0m0.703s
user 0m0.130s
sys 0m0.190s


chbrosch@brosch:~ > time find /var/spool/news/de/alt/fan/bluemchen/
-type f -maxdepth 1 -print | xargs grep Blümchen

[..]

real 0m0.695s
user 0m0.130s
sys 0m0.210s


chbrosch@brosch:~ > time echo /var/spool/news/de/alt/fan/bluemchen/*
| xargs grep Blümchen

[..]

real 0m1.171s
user 0m0.630s
sys 0m0.170s

Bis dann,

Christopher
--
|Ein Posting des Administrators von OSRAB --<-@ |
|Oberster Fanatischer Florist des Ordens der Dunklen Seite|
|von d.a.f.b.[tm] |
| http://christopherbrosch.de |

Anselm Lingnau

unread,
Jul 12, 2000, 3:00:00 AM7/12/00
to
Im Artikel <slrn8mp25...@brosch.heim-d.uni-sb.de> schrieb
Christopher Brosch <po...@christopherbrosch.de>:

> Der Befehl ist auf jeden Fall einfacher zu behalten als die anderen
> beiden. Ich habe mal die Geschwindigkeit dieser drei Möglichkeiten
> mittels time verglichen, interessanterweise braucht der kürzeste
> Befehl am längsten für die gleiche Aufgabe:
>
> chbrosch@brosch:~ > time find /var/spool/news/de/alt/fan/bluemchen/
> -maxdepth 1 -print | grep '/' | xargs grep Blümchen
>

> chbrosch@brosch:~ > time find /var/spool/news/de/alt/fan/bluemchen/
> -type f -maxdepth 1 -print | xargs grep Blümchen
>

> chbrosch@brosch:~ > time echo /var/spool/news/de/alt/fan/bluemchen/*
> | xargs grep Blümchen

Ohne jetzt im bash-Quellcode nachgeschaut zu haben, würde ich
vermuten, daß das daran liegt, daß bei Option 3 erst die komplette
Kommandozeile für »echo« gesammelt wird, bevor es mit dem »grep«
richtig losgeht. Bei den anderen beiden kriegt das »grep« schon ein
paar Dateinamen zur Bearbeitung zugeworfen, während das »find« noch
darauf wartet, daß die späteren Blöcke des Verzeichnisses sichtbar
werden.

Eine andere Anmerkung, die weniger mit Effizienz zu tun hat als mit
Robustheit im allgemeinen Fall. Alle diese Ansätze fallen auf die
Nase, wenn die Dateinamen Leerzeichen, Zeilenvorschübe o.ä. enthalten
(was sie ja ohne weiteres dürfen, auch wenn in einem Newsspool damit
weniger zu rechnen ist). Man sollte also etwas sagen wie

find ... -print0 | xargs --null grep Blümchen

um diese Fehlerquelle ein für allemal auszuschließen. Leider sind
diese Optionen nicht allgemein verbreitet; unter Linux mit den
GNU-Werkzeugen geht das aber.

Anselm
--
Anselm Lingnau ......................... lin...@tm.informatik.uni-frankfurt.de

Clearly bloat is not only a question of adding features almost no one wants.
Bloat is a condition of the mind, permeating software houses everywhere.
-- Rick A. Downes, RISKS Digest 20.35

Jost Boekemeier

unread,
Jul 12, 2000, 3:00:00 AM7/12/00
to
po...@christopherbrosch.de (Christopher Brosch) writes:

> beiden. Ich habe mal die Geschwindigkeit dieser drei Möglichkeiten
> mittels time verglichen, interessanterweise braucht der kürzeste
> Befehl am längsten für die gleiche Aufgabe

* matcht und sortiert die Einträge. find tut dies nicht. ls sortiert
ebenfalls, wenn man nicht -f angibt. `ls -f' sollte also die
schnellste Variante sein, gefolgt von find.


Jost

0 new messages