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

find/xargs

18 views
Skip to first unread message

Johannes Knelangen

unread,
Apr 17, 2013, 12:41:07 AM4/17/13
to
Hallo in de.comp.os.unix.shell!

Hier ist Johannes aus Bremen.

Die folgende Zeile macht in einer aktuellen bash nicht das, was ich
erwarten würde:

find -maxdepth 1 -type d -print0 | xargs -0 du -hs

Es wird lediglich die Größe des aktuellen Verzeichnisses, ".",
ausgegeben. Also praktisch das, was "du -hs ." ausgeben würde.

find -maxdepth 1 -type d -exec du -hs '{}' \;

macht dagegen das, was ich möchte, nämlich die Ausgabe der Gesamtgröße
für jedes direkte Unterverzeichnis.



Was ist an der Version mit xargs falsch, resp. wie muss ich diese
schreiben, damit das gleiche herauskommt wie bei dem Aufruf von find mit
Argument -exec ?

Herzliche Grüße aus der Bremer Innenstadt!



--
Johannes
"... ohne irgend weiter ein bitteres Gefühl, als das der allgemeinen Not der Welt ..."
(Heinrich v. Kleist)

Sascha Hüdepohl

unread,
Apr 17, 2013, 3:45:06 AM4/17/13
to
Hallo,

Johannes Knelangen <j.kne...@gmx.de> schrieb:

> find -maxdepth 1 -type d -print0 | xargs -0 du -hs
>
> Es wird lediglich die Größe des aktuellen Verzeichnisses, ".",
> ausgegeben. Also praktisch das, was "du -hs ." ausgeben würde.

Bei mir wird jedes Unterverzeichnis aufgelistet.

Hast Du mal geguckt was
$ find -maxdepth 1 -type d
ausgibt?

$ find --version
find (GNU findutils) 4.4.2


Gruß aus dem Bremer Technologiepark

Reinhard Tchorz

unread,
Apr 17, 2013, 8:50:58 AM4/17/13
to
Am 17.04.2013 06:41, schrieb Johannes Knelangen:
> Hallo in de.comp.os.unix.shell!
>
> Hier ist Johannes aus Bremen.
>
> Die folgende Zeile macht in einer aktuellen bash nicht das, was ich
> erwarten würde:
>
> find -maxdepth 1 -type d -print0 | xargs -0 du -hs
>
> Es wird lediglich die Größe des aktuellen Verzeichnisses, ".",
> ausgegeben. Also praktisch das, was "du -hs ." ausgeben würde.

Ist hier auch so.

> find -maxdepth 1 -type d -exec du -hs '{}' \;
>
> macht dagegen das, was ich möchte, nämlich die Ausgabe der Gesamtgröße
> für jedes direkte Unterverzeichnis.
>
>
>
> Was ist an der Version mit xargs falsch, resp. wie muss ich diese
> schreiben, damit das gleiche herauskommt wie bei dem Aufruf von find mit
> Argument -exec ?

Die xargs-Option -0 gibt ja nur den Trenner an. Zusätzlich muss man
xarg noch sagen, dass nur ein Argument, also eine Zeile von find, genommen
werden soll.

Das Ganze sieht dann so aus:
find -maxdepth 1 -type d -print0|xargs -0l1 du -hs

Gruss
Reinhard

--
Gentoo Kernel 3.8.6 X-Server 1.13.1 KDE 4.10.2
Asus M2A-VM AMD Athlon X2 4450e Nvidia 7300LE

Thomas 'PointedEars' Lahn

unread,
Apr 17, 2013, 9:05:55 AM4/17/13
to
Johannes Knelangen wrote:

> Hier ist Johannes aus Bremen.

Hallo. Sinnvoller wäre es gewesen, wenn Du geschrieben hättest, welches
System und welche Programmversionen Du benutzt. So kann man nur raten, dass
Du das System benutzt, mit dem Du postest – “User-Agent: Gnus/5.13 (Gnus
v5.13) Emacs/23.3 (*gnu*/linux)” – was aber der Problembeschreibung
irgendwie widerspricht.

> Die folgende Zeile macht in einer aktuellen bash nicht das, was ich
> erwarten würde:
>
> find -maxdepth 1 -type d -print0 | xargs -0 du -hs

“-maxdepth” und “-print0” sind Optionen/Operatoren von *GNU* find.

> Es wird lediglich die Größe des aktuellen Verzeichnisses, ".",
> ausgegeben. Also praktisch das, was "du -hs ." ausgeben würde.

Das deutet darauf hin, dass find(1) keine Ausgabe auf stdout erzeugt. xargs
erhält also keine weiteren Parameter über die Pipe und kann folglich auch
keine an du(1) übergeben. Also tut du(1) das, was es immer tut, wenn kein
Verzeichnis angegeben wird: es verwendet das aktuelle Verzeichnis (“.”).

> find -maxdepth 1 -type d -exec du -hs '{}' \;
>
> macht dagegen das, was ich möchte, nämlich die Ausgabe der Gesamtgröße
> für jedes direkte Unterverzeichnis.

Mit “-maxdepth” dürfte ein POSIX find(1) gar nichts tun (ausser eine
Fehlermeldung ausgeben). Das ist also wohl nicht der Grund, weshalb find(1)
hier nichts Sinnvolles ausgibt.

> Was ist an der Version mit xargs falsch,

Vermutlich generiert find(1) keine Ausgabe.

> resp. wie muss ich diese schreiben, damit das gleiche herauskommt wie bei
> dem Aufruf von find mit Argument -exec ?

POSIX-konform, was auch von GNU find(1) unterstützt wird, wäre

find . -name . -or -prune -type d -exec du -hs '{}' +

Die sichere Variante mit xargs bei GNU wäre

find . -maxdepth 1 -type d -print0 | xargs -0r du -hs --

Das verhindert erstens, dass du(1) aufgerufen wird, wenn xargs keine Eingabe
erhält (“-r”) und zweitens, dass Dateinamen, die mit “-” beginnen, von du(1)
als Optionen betrachtet werden (“--”)

--
PointedEars

Twitter: @PointedEars2
Please do not Cc: me. / Bitte keine Kopien per E-Mail.

Lutz Golke

unread,
Apr 17, 2013, 9:08:01 AM4/17/13
to
Am 17.04.2013 14:50, schrieb Reinhard Tchorz:
> Die xargs-Option -0 gibt ja nur den Trenner an. Zusätzlich muss man
> xarg noch sagen, dass nur ein Argument, also eine Zeile von find, genommen
> werden soll.
>
> Das Ganze sieht dann so aus:
> find -maxdepth 1 -type d -print0|xargs -0l1 du -hs


Das entspricht dann einem einfachen "du -d 1 -h", oder?

Gruß,
Lutz

Thomas 'PointedEars' Lahn

unread,
Apr 17, 2013, 9:12:35 AM4/17/13
to
Reinhard Tchorz wrote:

> Am 17.04.2013 06:41, schrieb Johannes Knelangen:
>> Die folgende Zeile macht in einer aktuellen bash nicht das, was ich
>> erwarten würde:
>>
>> find -maxdepth 1 -type d -print0 | xargs -0 du -hs
>>
>> Es wird lediglich die Größe des aktuellen Verzeichnisses, ".",
>> ausgegeben. Also praktisch das, was "du -hs ." ausgeben würde.
>
> Ist hier auch so.

Hier nicht. Beachte, dass “du -hs *” _nicht_ dasselbe ist wie „du -hs .”.

>> find -maxdepth 1 -type d -exec du -hs '{}' \;
>>
>> macht dagegen das, was ich möchte, nämlich die Ausgabe der Gesamtgröße
>> für jedes direkte Unterverzeichnis.
>>
>> Was ist an der Version mit xargs falsch, resp. wie muss ich diese
>> schreiben, damit das gleiche herauskommt wie bei dem Aufruf von find mit
>> Argument -exec ?
>
> Die xargs-Option -0 gibt ja nur den Trenner an. Zusätzlich muss man
> xarg noch sagen, dass nur ein Argument, also eine Zeile von find, genommen
> werden soll.
>
> Das Ganze sieht dann so aus:
> find -maxdepth 1 -type d -print0|xargs -0l1 du -hs

Das löst nicht das Problem, dass du(1) aufgerufen wird, wenn find(1) keine
Eingabe liefert, was hier offensichtlich der Fall ist.

Und xargs(1) wäre dann überflüssig:

find -maxdepth 1 -type d -exec du -hs '{}' \;

Aber das ist hier natürlich _nicht_ gesucht.

Thomas 'PointedEars' Lahn

unread,
Apr 17, 2013, 9:38:44 AM4/17/13
to
Ja, bei GNU du(1). POSIX du(1) kennt nur die Optionen -a, -H, -k, -L, -s
und -x.

<http://pubs.opengroup.org/onlinepubs/9699919799/utilities/du.html>

Johannes Knelangen

unread,
Apr 17, 2013, 9:56:09 AM4/17/13
to
Reinhard Tchorz <rtc...@t-online.de> writes:

> Am 17.04.2013 06:41, schrieb Johannes Knelangen:
>> Hallo in de.comp.os.unix.shell!
>>
>> Hier ist Johannes aus Bremen.
>>
>> Die folgende Zeile macht in einer aktuellen bash nicht das, was ich
>> erwarten würde:
>>
>> find -maxdepth 1 -type d -print0 | xargs -0 du -hs
>>
>> Es wird lediglich die Größe des aktuellen Verzeichnisses, ".",
>> ausgegeben. Also praktisch das, was "du -hs ." ausgeben würde.
>
> Ist hier auch so.
>
>> find -maxdepth 1 -type d -exec du -hs '{}' \;
>>
>> macht dagegen das, was ich möchte, nämlich die Ausgabe der Gesamtgröße
>> für jedes direkte Unterverzeichnis.
>>
>>
>>
>> Was ist an der Version mit xargs falsch, resp. wie muss ich diese
>> schreiben, damit das gleiche herauskommt wie bei dem Aufruf von find mit
>> Argument -exec ?
>
> Die xargs-Option -0 gibt ja nur den Trenner an. Zusätzlich muss man
> xarg noch sagen, dass nur ein Argument, also eine Zeile von find, genommen
> werden soll.
>
> Das Ganze sieht dann so aus:
> find -maxdepth 1 -type d -print0|xargs -0l1 du -hs

Jawoll, so geht's!
Habe zwar noch nicht verstanden, was -l u. -1 anrichten, aber das kann
ich ja nachlesen.

Danke!

>
> Gruss
> Reinhard

Johannes Knelangen

unread,
Apr 17, 2013, 10:01:55 AM4/17/13
to
Thomas 'PointedEars' Lahn <Point...@web.de> writes:

>
> Hallo. Sinnvoller wäre es gewesen, wenn Du geschrieben hättest, welches
> System und welche Programmversionen Du benutzt. So kann man nur raten, dass
> Du das System benutzt, mit dem Du postest – “User-Agent: Gnus/5.13 (Gnus
> v5.13) Emacs/23.3 (*gnu*/linux)” – was aber der Problembeschreibung
> irgendwie widerspricht.
>
>
> “-maxdepth” und “-print0” sind Optionen/Operatoren von *GNU* find.
>

ach!

uname -a :
Linux tpr500 3.2.0-41-generic #65-Ubuntu SMP Wed Apr 10 18:25:50 UTC
2013 x86_64 x86_64 x86_64 GNU/Linu

find --version :
find (GNU findutils) 4.4.2

xargs --version
xargs (GNU findutils) 4.4.2



>
> Das deutet darauf hin, dass find(1) keine Ausgabe auf stdout erzeugt. xargs
> erhält also keine weiteren Parameter über die Pipe und kann folglich auch
> keine an du(1) übergeben. Also tut du(1) das, was es immer tut, wenn kein
> Verzeichnis angegeben wird: es verwendet das aktuelle Verzeichnis (“.”).
>

find ohne die pipe zu xargs erzeugt genau die Ausgabe, die ich erwarten
würde:

Mit print ein Verzeichnis / Zeile,
mit print0 alle Verzeichnisse in einer Zeile. Der Null-Trenner bewirkt
ja nichts in der Ausgabe auf stdout.


find -maxdepth 1 -type d -print0 | xargs -0l1 du -hs

macht es dann so, wie es soll.

Danke an Thomas Lahn.

Ich muss allerdings noch nachlesen, warum das so ist.


Vielen Dank für Eure Antworten!

Thomas 'PointedEars' Lahn

unread,
Apr 17, 2013, 12:05:30 PM4/17/13
to
Johannes Knelangen wrote:

> Thomas 'PointedEars' Lahn <Point...@web.de> writes:
>> Hallo. Sinnvoller wäre es gewesen, wenn Du geschrieben hättest, welches
>> System und welche Programmversionen Du benutzt. So kann man nur raten,
>> dass Du das System benutzt, mit dem Du postest – “User-Agent: Gnus/5.13
>> (Gnus v5.13) Emacs/23.3 (*gnu*/linux)” – was aber der Problembeschreibung
>> irgendwie widerspricht.
>>
>> “-maxdepth” und “-print0” sind Optionen/Operatoren von *GNU* find.
>
> ach!
>
> uname -a :
> Linux tpr500 3.2.0-41-generic #65-Ubuntu SMP Wed Apr 10 18:25:50 UTC
> 2013 x86_64 x86_64 x86_64 GNU/Linu
>
> find --version :
> find (GNU findutils) 4.4.2
>
> xargs --version
> xargs (GNU findutils) 4.4.2

Das Problem gibt es also unter *GNU*/Linu_x_ mit *GNU* find und *GNU*
xargs(1). Das hättest Du eben in de.comp.os.*unix*.shell gleich
dazuschreiben sollen/müssen (GNU's _Not_ Unix).

Hier:

$ find --version | head -n 1
find (GNU findutils) 4.4.2

$ xargs --version | head -n 1
xargs (GNU findutils) 4.4.2

$ du --version | head -n 1
du (GNU coreutils) 8.13

$ uname -srvmo
Linux 3.4.39-pe #1 SMP Sat Apr 6 00:04:40 CEST 2013 i686 GNU/Linux

$ cat /etc/debian_version
7.0

Das von Dir beschriebene Verhalten lässt sich hier _nicht_ reproduzieren.

>> Das deutet darauf hin, dass find(1) keine Ausgabe auf stdout erzeugt.
>> xargs erhält also keine weiteren Parameter über die Pipe und kann
>> folglich auch
>> keine an du(1) übergeben. Also tut du(1) das, was es immer tut, wenn
>> kein Verzeichnis angegeben wird: es verwendet das aktuelle Verzeichnis
>> (“.”).
>
> find ohne die pipe zu xargs erzeugt genau die Ausgabe, die ich erwarten
> würde:
>
> Mit print ein Verzeichnis / Zeile,
> mit print0 alle Verzeichnisse in einer Zeile.
> Der Null-Trenner bewirkt ja nichts in der Ausgabe auf stdout.

Wenn find(1) ungültige Optionen übergeben bekommt oder sonst irgendetwas
schiefläuft, spielt es keine Rolle, ob Du “-print” oder “-print0”
verwendest.

Anscheinend ist Dir Folgendes nicht klar:

“-print0” bewirkt, dass die Suchergebnisse mit <NUL> statt mit <LF> getrennt
werden. Das macht man, weil <NUL> in Dateinamen eher nicht vorkommt; <LF>
könnte hingegen vorkommen und xargs(1) würde dann das <LF> im Dateinamen als
Argumenttrenner behandeln. Unter anderem deshalb gibt es “-print0” für
*GNU* find(1) und “-0” für *GNU* xargs(1).

> find -maxdepth 1 -type d -print0 | xargs -0l1 du -hs
>
> macht es dann so, wie es soll.

Das finde ich *sehr* seltsam.

> Danke an Thomas Lahn.

Gern geschehen. Wir duzen uns hier aber normalerweise.

> Ich muss allerdings noch nachlesen, warum das so ist.

Ich bin auf Deine Erkenntnisse gespannt.

Reinhard Tchorz

unread,
Apr 17, 2013, 2:26:01 PM4/17/13
to
Am 17.04.2013 18:05, schrieb Thomas 'PointedEars' Lahn:
> Johannes Knelangen wrote:
>
> Hier:
>
> $ find --version | head -n 1
> find (GNU findutils) 4.4.2
>
> $ xargs --version | head -n 1
> xargs (GNU findutils) 4.4.2
>
> $ du --version | head -n 1
> du (GNU coreutils) 8.13
>
> $ uname -srvmo
> Linux 3.4.39-pe #1 SMP Sat Apr 6 00:04:40 CEST 2013 i686 GNU/Linux
>
> $ cat /etc/debian_version
> 7.0
>
> Das von Dir beschriebene Verhalten lässt sich hier _nicht_ reproduzieren.

Hier aber schon.

> Wenn find(1) ungültige Optionen übergeben bekommt oder sonst irgendetwas
> schiefläuft, spielt es keine Rolle, ob Du “-print” oder “-print0”
> verwendest.

Na klar. Fehlermeldungen kämen dann aber trotzdem über stderr.
>
> Anscheinend ist Dir Folgendes nicht klar:
>
>> find -maxdepth 1 -type d -print0 | xargs -0l1 du -hs
>>
>> macht es dann so, wie es soll.
>
> Das finde ich *sehr* seltsam.

Interessante Sache :-)
Habe mal nach der möglichen Ursache wegen dem unterschiedlichen Verhalten gesucht.

~/Documents> find -maxdepth 1 -type d -print0|xargs -0 --interactive du -hs
du -hs . ./Jeans ./Notizen ./backup ./buecher ./docbook ./dokus ./office ./smava ./testbild ?...y
1,2G .

Da wird also lediglich der Speicher für das aktuelle Verzeichnis berechnet.

~/Documents> du -hs Notizen/ buecher/
544K Notizen/
103M buecher/

Korrekt.

~/Documents> du -hs . Notizen/ buecher/
1,2G .

Falsch!

~/Documents> du -hs Notizen/ . buecher/
544K Notizen/
1,2G .

Auch falsch!

Es sieht so aus, als wenn 'du' abbricht, sobald ein . in der Liste der Verzeichnisse auftaucht.
Ist IMHO ein Fehler in du.

~/Documents> du --version|head -n 1
du (GNU coreutils) 8.20

Gruß

Stefan Froehlich

unread,
Apr 17, 2013, 3:30:51 PM4/17/13
to
On Wed, 17 Apr 2013 20:26:01 Reinhard Tchorz wrote:
> ~/Documents> du -hs Notizen/ . buecher/
> 544K Notizen/
> 1,2G .

> Es sieht so aus, als wenn 'du' abbricht, sobald ein . in der Liste der
> Verzeichnisse auftaucht.
> Ist IMHO ein Fehler in du.

Scheint so, ja.

> ~/Documents> du --version|head -n 1
> du (GNU coreutils) 8.20

Spannend. Spontan habe ich hier einmal Debian/Squeeze und einmal
Debian/Wheezy zur Verfuegung:

| sfroehli@sokrates:~$ du --version | head -n 1
| du (GNU coreutils) 8.5
| sfroehli@sokrates:~$ du -hs test1/ . test2/
| 4.0K test1/
| 199G .
| 4.0K test2/

| sfroehli@hosted-by:~$ du --version | head -n 1
| du (GNU coreutils) 8.13
| sfroehli@hosted-by:~$ du -hs test1/ . test2/
| 4.0K test1/
| 832K .

Irgendwo dazwischen wurde also wohl etwas kaputtgemacht.

Servus,
Stefan

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

Stefan - manierlich, herzig in allen Überschwemmungen!
(Sloganizer)

Johannes Knelangen

unread,
Apr 17, 2013, 8:32:06 PM4/17/13
to
Danke an Reinhard Tchorz hätte es heissen müssen.


> Gern geschehen. Wir duzen uns hier aber normalerweise.
>

Wir auch.
SCNR. Habe mich wie gesagt mit dem Namen vertan.



>> Ich muss allerdings noch nachlesen, warum das so ist.
>
> Ich bin auf Deine Erkenntnisse gespannt.

Wie mittlerweile andere schon gepostet haben, scheint es sich um einen
Fehler im du zu handeln.

Mit anderen Befehlen als Argument für xargs wie bspw.

find -maxdepth 1 -type d -print0 | xargs -0 ls -ld

wird die richtige Argumentenliste abgearbeitet.


Warum allerdings dann das

find -maxdepth 1 -type d -print0 | xargs -0l1 du -hs

doch wieder alles richtig macht, will sich mir auch nach erneuter
Lektüre der xargs man-page nicht erschliessen. Aber wenn's tatsächlich
ein Fehler im du ist, braucht mich das ja auch nicht weiter zu
beunruhigen ...

Thomas 'PointedEars' Lahn

unread,
Apr 18, 2013, 9:23:18 AM4/18/13
to
Reinhard Tchorz wrote:

> Am 17.04.2013 18:05, schrieb Thomas 'PointedEars' Lahn:
>> Johannes Knelangen wrote:
>>
>> Hier:
>>
>> $ find --version | head -n 1
>> find (GNU findutils) 4.4.2
>>
>> $ xargs --version | head -n 1
>> xargs (GNU findutils) 4.4.2
>>
>> $ du --version | head -n 1
>> du (GNU coreutils) 8.13
>>
>> $ uname -srvmo
>> Linux 3.4.39-pe #1 SMP Sat Apr 6 00:04:40 CEST 2013 i686 GNU/Linux
>>
>> $ cat /etc/debian_version
>> 7.0
>>
>> Das von Dir beschriebene Verhalten lässt sich hier _nicht_ reproduzieren.
>
> Hier aber schon.

Hier auch, ich hatte wohl nicht richtig getestet.

$ du -hs . bla/
472M .

$ du -hs bla/ .
56K bla/
472M .

$ du --version | head -n 1
du (GNU coreutils) 8.13

> […]
> Es sieht so aus, als wenn 'du' abbricht, sobald ein . in der Liste der
> Verzeichnisse auftaucht. Ist IMHO ein Fehler in du.
>
> ~/Documents> du --version|head -n 1
> du (GNU coreutils) 8.20

ACK.
0 new messages