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

Mit find immer nur das tiefste Verzeichnis finden

4 views
Skip to first unread message

Karl Teuschler

unread,
Jul 23, 2010, 6:21:29 AM7/23/10
to
Hallo,

Ich möchte mit find "unabhängig" vom aufgerufenen Verzeichnis immer
nur das am tiefsten liegende Verzeichnis finden.

Also in meiner BeispielVerzeichnissstruktur, möchte ich
--------------------------------------------------------
tmp/verzeichnis1/baum1/dir1/dir2
tmp/verzeichnis1/baum2/dir1
tmp/verzeichnis1/baum3/dir1/dir2/dir3
--------------------------------------------------------
finden.

Wie macht man soetwas mit find?

Vielen Dank im Voraus
Karl

Achim Peters

unread,
Jul 23, 2010, 6:37:22 AM7/23/10
to
Karl Teuschler wrote:
> Ich möchte mit find "unabhängig" vom aufgerufenen Verzeichnis immer
> nur das am tiefsten liegende Verzeichnis finden.
>
> Also in meiner BeispielVerzeichnissstruktur, möchte ich
> --------------------------------------------------------
> tmp/verzeichnis1/baum1/dir1/dir2
> tmp/verzeichnis1/baum2/dir1
> tmp/verzeichnis1/baum3/dir1/dir2/dir3
> --------------------------------------------------------
> finden.

Zu dem Zeitpunkt, wo find ein Directory findet, weiß es nicht, ob in dem
Directory noch weitere Directorys sind. Mit find alleine geht es daher
IMO nicht.

Du könntest find alle Directorys finden lassen und die einzelnen
Ergebnisse dann in einer Schleife jeweils um "/" ergänzt mit grep gegen
die ganze Ergebnisliste abtesten. Was nicht gefunden wird, ist ein Blatt
im Baum.

HTH

Bye
Achim

Paul Hink

unread,
Jul 23, 2010, 7:21:32 AM7/23/10
to
Karl Teuschler <karl111.20...@spamgourmet.com> wrote:

Ohne jetzt länger darüber nachgedacht zu haben, inwiefern diese
Konstruktion portabel ist und welche Sonderfälle sie u.U. nicht
berücksichtigt (mindestens auf Systemen, die Hardlinks auf
Verzeichnisse erlauben, funktioniert das nicht zuverlässig):

$ find <path> -type d -links 2

Erklärung: Jedes Verzeichnis hat mindestens zwei Links, nämlich den im
übergeordneten Verzeichnis und den "."-Eintrag im jeweiligen
Verzeichnis selbst. Für jedes Unterverzeichnis kommt dann noch je ein
Link hinzu, nämlich der ".."-Eintrag im jeweiligen Unterverzeichnis.
Allgemein hat also ein Verzeichnis mit n Unterverzeichnissen genau
(n+2) Links.

Helmut Hullen

unread,
Jul 23, 2010, 8:05:00 AM7/23/10
to
Hallo, Karl,

Du meintest am 23.07.10:

Ergänzend zu Achims Hinweisen: wie wäre es mit

ls -lR /tmp/verzeichnis1

zur Vorbereitung, und dann werden alle Dateien und Unterverzeichnisse
aussortiert?

Mögliche Suchbegriffe:
- Zeile vor "total"
- Zeile mit "/"

Und dann zählst Du "/"

Vielleicht geht auch

cd /tmp
ls -lR . | grep ^./verzeichnis1

als Vorbereitung.

Viele Gruesse
Helmut

"Ubuntu" - an African word, meaning "Slackware is too hard for me".

Ansgar Strickerschmidt

unread,
Jul 23, 2010, 8:44:45 AM7/23/10
to
Also schrieb Karl Teuschler:


Mein Vorschlag: Skript "testfind1"

----<schnipp>----

#!/bin/bash

# Zu testendes Verzeichnis aus Aufrufparameter übernehmen, sonst
Default=aktuelles Verzeichnis:
TARGET_DIR="${1:-$PWD}"

for i in `find "$TARGET_DIR" -type d`; do
lowest=1
for j in `find "$i" -mindepth 1 -type d` ; do
lowest=0
break
done

if [ $lowest -eq 1 ] ; then
# ... hatte i kein weiteres Unterverzeichnis, das die Variable auf 0
gesetzt hätte:
echo "$i"
fi
done

----<schnapp>----

Keine Ahnung, ob das unter allen Eventualitäten funktioniert...

Ansgar

--
*** Musik! ***

Ansgar Strickerschmidt

unread,
Jul 23, 2010, 8:56:44 AM7/23/10
to
Also schrieb Ansgar Strickerschmidt:

> Also schrieb Karl Teuschler:
>
>> Hallo,
>>
>> Ich möchte mit find "unabhängig" vom aufgerufenen Verzeichnis immer
>> nur das am tiefsten liegende Verzeichnis finden.
>>
>> Also in meiner BeispielVerzeichnissstruktur, möchte ich
>> --------------------------------------------------------
>> tmp/verzeichnis1/baum1/dir1/dir2
>> tmp/verzeichnis1/baum2/dir1
>> tmp/verzeichnis1/baum3/dir1/dir2/dir3
>> --------------------------------------------------------
>> finden.
>>
>> Wie macht man soetwas mit find?
>
>

Nochmal nachgedacht und umgebaut: Skript "testfind2"

----<schnipp>----

#!/bin/bash

TARGET_DIR="${1:-$PWD}"

for i in `find "$TARGET_DIR" -type d`; do

if [ -z "`find "$i" -mindepth 1 -type d`" ] ; then
echo "$i"
fi
done

----<schnapp>----

:)

Karl Teuschler

unread,
Jul 23, 2010, 11:38:49 AM7/23/10
to
> $ find <path> -type d -links 2
Funktioniert bei mir(Ubuntu 9.10) einwandfrei.

Danke
Karl

Karl Teuschler

unread,
Jul 23, 2010, 1:49:04 PM7/23/10
to
> ----<schnipp>----
>
> #!/bin/bash
>
> TARGET_DIR="${1:-$PWD}"
>
> for i in `find "$TARGET_DIR" -type d`; do
>    if  [ -z "`find "$i" -mindepth 1 -type d`" ] ; then
>       echo "$i"
>    fi
> done
>
> ----<schnapp>----

Funktioniert auch wunderbar!

danke
Karl

David Haller

unread,
Jul 24, 2010, 12:35:49 AM7/24/10
to
Ansgar Strickerschmidt <dropspamhe...@arcor.de> wrote:
> for i in `find "$TARGET_DIR" -type d`; do

mkdir "${TARGET_DIR}/ker plauz"

Und tschüß!

-dnh

--
/ "[the block drivers and the buffer cache] aren't incestuous, \
\ they're just living in sin.. " -- Linus Torvalds /

Mart Frauenlob

unread,
Jul 24, 2010, 2:00:04 AM7/24/10
to
On 24.07.2010 06:35, David Haller wrote:
> Ansgar Strickerschmidt<dropspamhe...@arcor.de> wrote:
>> for i in `find "$TARGET_DIR" -type d`; do
>
> mkdir "${TARGET_DIR}/ker plauz"


Darum:

find ... | while IFS= read -r; do irgendwas "$REPLY"; done

oder,

while IFS= read -r; do irgendwas "$REPLY"; done < <(find ...)

oder (geht auch mit Dateien mit Zeilenumbruch im Namen) (GNU),

find ... -print0 | xargs -0 irgendwas


lg Mart

Sven Mascheck

unread,
Jul 24, 2010, 12:04:00 PM7/24/10
to
Mart Frauenlob wrote:

> oder (geht auch mit Dateien mit Zeilenumbruch im Namen) (GNU),
>
> find ... -print0 | xargs -0 irgendwas

oder allgemeiner, ebenfalls beschleunigt,

find ... -exec irgendwas {} +

(mit irgendwas z.B. "sh -c 'for i; do ...' find-sh")

David Haller

unread,
Jul 26, 2010, 1:20:45 AM7/26/10
to
Sven Mascheck <masc...@email.invalid> wrote:
> Mart Frauenlob wrote:
>> oder (geht auch mit Dateien mit Zeilenumbruch im Namen) (GNU),
>>
>> find ... -print0 | xargs -0 irgendwas
>
> oder allgemeiner, ebenfalls beschleunigt,
>
> find ... -exec irgendwas {} +

Zumindest wenn "find" kein zu altes GNU-find (oder sonst ein
"kapottes") ist (mein eines GNU-find ist zu alt) ;)



> (mit irgendwas z.B. "sh -c 'for i; do ...' find-sh")

... und im 'do ..; done' immer schön "$i" quoten, sonst knallt man
auch da prompt wieder auf die Fresse! BTW: ich nehm bei sowas (hier
iterieren über Verz./Dateien) immer d bzw. f als Variablennamen ;)

-dnh, *huch*, nochmal die gleiche Zufallssig wie im letzten Post!
wird aber ersetzt, öhm, ich nehm mal einfach die neueste ;)

PS@Sven: da ich weiß, du "sammelst" solche Eigenarten, wenn du noch
Details von mir zu ~11 Jahre altem GNU Krams willst (inkl. Tests
und manpages) solltest du dich beeilen, da die Kiste ausgemustert
werden soll. Doku (man-/infopages) gingen auch später noch, aber
da steht halt nicht unbedingt immer alles drin ... Hm. Vielleicht
sollte ich einiges noch in ne VM umziehen, Plattenplatz hätte ich.
$ rpm -qa --last | tail -1
bc-1.04-74 Mon 16 Aug 1999 07:19:26
*g* (und CPU/MoBo sind vom Sommer 2000, der Rest teils deutlich
älter, teils "brandneu" :) Ein 2 Monate alter TFT an ner Mystique
von 1995 ... Hat sowas sonst noch wer als Hauptrechner? ;)

--
Sheridan: "I'll tell you one thing. If the primates that we came from had
known that some day politicians would come out of the gene pool, they'd have
stayed up in the trees and written evolution off as a bad idea!"
-- Babylon 5, 2x04 - A Distant Star

Ansgar Strickerschmidt

unread,
Jul 26, 2010, 4:26:33 AM7/26/10
to
Also schrieb David Haller:

> Ansgar Strickerschmidt <dropspamhe...@arcor.de> wrote:
>> for i in `find "$TARGET_DIR" -type d`; do
>
> mkdir "${TARGET_DIR}/ker plauz"

mkdir "Wer Leerzeichen in Verzeichnisnamen verwendet frisst auch kleine
Kinder"

Ansgar Strickerschmidt

unread,
Jul 26, 2010, 4:36:32 AM7/26/10
to
Also schrieb Sven Mascheck:

Das ist mir jetzt ein wenig zu kryptisch... -v, bitte, damit Lernende wie
ich auch mitkommen... so ein kleines kommentiertes Beispiel wäre nett.

Mart Frauenlob

unread,
Jul 26, 2010, 4:57:05 AM7/26/10
to
man find:

-exec command {} +
This variant of the -exec action runs the specified
command on the selected files, but the command line is built by
appending each selected file
name at the end; the total number of invocations of the
command will be much less than the number of matched files. The command
line is built in
much the same way that xargs builds its command lines.
Only one instance of `{}' is allowed within the command. The command is
executed in the
starting directory.


-print0
True; print the full file name on the standard output,
followed by a null character (instead of the newline character that
-print uses). This
allows file names that contain newlines or other types
of white space to be correctly interpreted by programs that process the
find output. This
option corresponds to the -0 option of xargs.

wüsste nicht was ich da noch erklären sollte/könnte...

Mart Frauenlob

unread,
Jul 26, 2010, 5:12:47 AM7/26/10
to


Kein Grund nicht darauf vorbereitet zu sein.

Paul Hink

unread,
Jul 26, 2010, 10:53:30 AM7/26/10
to

Mit dem (vermutlich ungewollten) Zeilenumbruch im "Verzeichnisnamen"
bekommt diese Aussage eine ganz neue Dimension.

Ansgar Strickerschmidt

unread,
Jul 26, 2010, 11:03:27 AM7/26/10
to
Also schrieb Paul Hink:

Ich sehe da keinen.

Message has been deleted

Sven Mascheck

unread,
Jul 26, 2010, 7:25:04 PM7/26/10
to
Ansgar Strickerschmidt wrote:
> Also schrieb Sven Mascheck:

>
>> find ... -exec irgendwas {} +
>>
>> (mit irgendwas z.B. "sh -c 'for i; do ...' find-sh")
>
> -v, bitte

Falls mehr als ein simples Kommando "irgendwas" benötigt wird,
also im allgemeinen Fall ein kleines Skript, dann ist der
genannte Shell-Aufruf eine Anregung, etwas passendes zu bauen.
Mit einer Shell-Schleife ist es bei wirklich vielen Argumenten
allerdings schon wieder relativ langsam.

Manchmal reicht eine Shell ohne Schleife aber schon aus.
Schönes Beispiel: Man möchte die gefundenen Argumente in ein
anderes Verzeichnis verschieben. Das + muß direkt auf {}
folgen, deshalb wäre folgendes ungültig,

find ... -exec mv {} /targetdir/ +

(Manche mv(1) bieten als Workaround an, das Directory mit
einer Option vor den Argumenten zu übergeben, aber darum
geht's hier nicht.)

Eine (dennoch sehr schnelle) Möglichkeit mit Shell ist

find ... -exec sh -c 'mv "$@" /targetdir/' find-sh {} +

Sprich:
Es mag natürlich jeweils speziellere Lösungen geben,
die schlanker, schneller, etc. sind. Aber zumindest kann
man mit "-exec +" und sh -c '...' (ggf. mit einer Schleife)
relativ einfach stets eine völlig robuste Lösung bauen.
OpenBSD, busybox und so manches ältere System kennen "-exec +"
noch nicht; dann gibt's vielleicht -print0|xargs -0.
Das ist insgesamt gesehen aber nicht besser verbreitet
und hat gelegentlich auch seine Tücken.


In der Praxis reicht ja in vielen Fällen ohnehin ein
"find ...|xargs" aus, aber die interessante Frage ist ja,
wie es bei Bedarf robust wird.

Randbemerkung: Häufig wird es bei "-exec +" bei einem einzigen
Aufruf bleiben, woran man sich gewöhnen kann. Man darf nie vergessen,
daß bei sehr vielen Argumenten mehrere Aufrufe daraus folgen können.
--
http://www.in-ulm.de/~mascheck/various/find/

Sven Mascheck

unread,
Jul 26, 2010, 7:37:40 PM7/26/10
to
David Haller wrote:

> Zumindest wenn "find" kein zu altes GNU-find (oder sonst ein
> "kapottes") ist (mein eines GNU-find ist zu alt) ;)

Ja, bei GNU wurde es zwischen Jan'05 und Aug'06 eingeführt.
Letztendlich ist die Situation bzgl. der Verbreitung bei -print0
nicht anders, "-exec +" hat aber bessere Karten für die Zukunft,
da in POSIX. Mehr Details zur Verbreitung sammele ich in .sig.

> [ ~11 Jahre altem GNU Krams ]

Danke, aber mit etwas Zeit fand ich im Netz sogar noch
Source wie GNU find-3.2 ('91), -3.8 ('93), -4.0 ('94)

--
http://www.in-ulm.de/~mascheck/various/find/

Paul Hink

unread,
Jul 27, 2010, 3:42:33 AM7/27/10
to
Sven Mascheck <masc...@email.invalid> wrote:

> Eine (dennoch sehr schnelle) Möglichkeit mit Shell ist
>
> find ... -exec sh -c 'mv "$@" /targetdir/' find-sh {} +
>
> Sprich:
> Es mag natürlich jeweils speziellere Lösungen geben,
> die schlanker, schneller, etc. sind. Aber zumindest kann
> man mit "-exec +" und sh -c '...' (ggf. mit einer Schleife)
> relativ einfach stets eine völlig robuste Lösung bauen.

Richtig. Man muss dabei aber natürlich auch noch die Eigenheiten der
von der Shell aufgerufenen Kommandos im Auge behalten. Hier z.B.
mögliche Nebeneffekte bei Dateinamen, die mit einem Minus beginnen...

Ansgar Strickerschmidt

unread,
Jul 27, 2010, 4:11:07 AM7/27/10
to
Also schrieb Sven Mascheck:

> Ansgar Strickerschmidt wrote:
>> Also schrieb Sven Mascheck:
>>
>>> find ... -exec irgendwas {} +
>>>
>>> (mit irgendwas z.B. "sh -c 'for i; do ...' find-sh")
>>
>> -v, bitte
>

> ...(Ausführliches)...

> Randbemerkung: Häufig wird es bei "-exec +" bei einem einzigen
> Aufruf bleiben, woran man sich gewöhnen kann. Man darf nie vergessen,
> daß bei sehr vielen Argumenten mehrere Aufrufe daraus folgen können.

OK, da muss ich wohl mal damit spielen. Ich hab's jedenfalls mal
aufgehoben...

Ansgar Strickerschmidt

unread,
Jul 27, 2010, 4:25:30 AM7/27/10
to
Also schrieb Torsten Fleischmann:

>>>> mkdir "Wer Leerzeichen in Verzeichnisnamen verwendet frisst auch
>>>> kleine
>>>> Kinder"
>
>>> Mit dem (vermutlich ungewollten) Zeilenumbruch im "Verzeichnisnamen"
>>> bekommt diese Aussage eine ganz neue Dimension.
>
>> Ich sehe da keinen.
>

> Na dann ließ dir den mkdir Befehl noch mal durch ;-)

?
Ich steh grad auf dem Schlauch...
Habe mein Letzteres mal durchgeführt (alle evtl. Umbrüche kommen vom
Newsreader...):

alpha@alpha04:~$ cd test1/
alpha@alpha04:~/test1$ mkdir "Wer Leerzeichen in Verzeichnisnamen

verwendet frisst auch kleine Kinder"

alpha@alpha04:~/test1$ ls -l
...
drwxr-xr-x 2 alpha alpha 4096 2010-07-27 10:11 Wer Leerzeichen in

Verzeichnisnamen verwendet frisst auch kleine Kinder

alpha@alpha04:~/test1$ cd Wer\ Leerzeichen\ in\ Verzeichnisnamen\
verwendet\ frisst\ auch\ kleine\ Kinder/
alpha@alpha04:~/test1/Wer Leerzeichen in Verzeichnisnamen verwendet frisst
auch kleine Kinder$ ls
alpha@alpha04:~/test1/Wer Leerzeichen in Verzeichnisnamen verwendet frisst
auch kleine Kinder$

Oder meintet ihr etwas vom Vorhergehenden?

Sven Mascheck

unread,
Jul 27, 2010, 2:15:55 PM7/27/10
to
Paul Hink wrote:

>> [...] mit "-exec +" und sh -c '...' (ggf. mit einer Schleife) [...]


>
> Richtig. Man muss dabei aber natürlich auch noch die Eigenheiten der
> von der Shell aufgerufenen Kommandos im Auge behalten. Hier z.B.
> mögliche Nebeneffekte bei Dateinamen, die mit einem Minus beginnen...

..und um Beispielen zu geben, also dem Trenner "--" zwischen Optionen
und Argumenten, wenn unterstützt. Oder z.B. auch durch Voranstellen
von ./ (einer simplen, gern übersehenen Lösung),

sh -c 'for i; do echo "./$i"; done'

Sven Mascheck

unread,
Jul 27, 2010, 3:22:26 PM7/27/10
to
Paul Hink wrote:

>> [...] mit "-exec +" und sh -c '...' (ggf. mit einer Schleife) [...]


>
> Richtig. Man muss dabei aber natürlich auch noch die Eigenheiten der
> von der Shell aufgerufenen Kommandos im Auge behalten. Hier z.B.
> mögliche Nebeneffekte bei Dateinamen, die mit einem Minus beginnen...

..und um Beispiele zu geben, also der Trenner "--" zwischen Optionen


und Argumenten, wenn unterstützt. Oder z.B. auch durch Voranstellen
von ./ (einer simplen, gern übersehenen Lösung),

sh -c 'for i; do echo "./$i"; done'

[supersede meines ersten posts mit hervorragendem Deutsch]

Thomas Rachel

unread,
Aug 2, 2010, 9:30:34 PM8/2/10
to
Am 2010-07-26 17:03 schrieb Ansgar Strickerschmidt:

>> Mit dem (vermutlich ungewollten) Zeilenumbruch im "Verzeichnisnamen"
>> bekommt diese Aussage eine ganz neue Dimension.
>
> Ich sehe da keinen.

Die Rohansicht des Postings bringt Klarheit.

Im übrigen sind bei robuster Programmierung auch Zeilenumbrüche in
Dateinamen kein Problem.


Thomas

0 new messages