![](https://seccdn.libravatar.org/avatar/ffcbb0f1ce7068f1fde373b35ab383f4.jpg?s=120&d=mm&r=g)
Ich suche eine Lösung zu folgendem Problem: Aus organisatorischen Gründen muss ich hier einen Haufen Skripte mit einem kryptischen Namen versehen, der einer Namenskonvention eines Theoretikers entspringt Ausserdem müssen die Teile in einem Standardverzeichnis abgelegt werden. Da ich meine eigentlichen Skripte nicht umbenennen will, habe ich "kryptische" Links angelegt, die auf meine Skripte mit sprechendem Namen zeigen. Nun werden aus den Skripten viele Reports, Mails, SMS, Logs, Datenbankeinträge etc. generiert, die sich irgendwie aus Skriptname (basename) und Verzeichnisname (dirname) des Skriptes ergeben. Viele "Log-Dirs" liegen auch unterhalb oder parallel zu den jeweiligen "Script-Dirs". Leider liefert basename/dirname nicht den Namen des echten Skriptes sondern den des Links wenn die Teile unter dem Linknamen gestartet werden. Kann man irgendwie elegant das ganze lösen? (Keine Bastellösung der Art: mach mal ein ls und schau, ob es ein link es, wenn ja, ...) Auch eine Antwort "geht nicht, du musst basteln" ist OK (Das Basteln mache ich dann schon selber!) Andreas
![](https://seccdn.libravatar.org/avatar/ebe9e7470f033d101415722d029f0b24.jpg?s=120&d=mm&r=g)
Andreas Kyek <a.kyek@vodafone.com>:
Leider liefert basename/dirname nicht den Namen des echten Skriptes sondern den des Links wenn die Teile unter dem Linknamen gestartet werden.
in der Shell weiss ich nicht, aber Perl kann das. in der Shell: x=abc; xx=`perl -e"printf \"%s\n\" ,readlink (\"$x\")"`; echo $xx ist abc eine Datei ist $x leer. ist abc ein symlink auf 123, dann wird 123 ausgegeben Jürgen -- Dr.rer.nat. Juergen Vollmer, Viktoriastrasse 15, D-76133 Karlsruhe Tel: +49(721) 9204871 Fax: +49(721) 24874 Juergen.Vollmer@[informatik-vollmer.de|alumni.uni-karlsruhe.de|acm.org] www.informatik-vollmer.de
![](https://seccdn.libravatar.org/avatar/7b33cb1e776e35b87edb8ef09f0c888f.jpg?s=120&d=mm&r=g)
Hallo, Am Thu, 18 Sep 2003, Andreas Kyek schrieb:
Ich suche eine Lösung zu folgendem Problem: [..] Da ich meine eigentlichen Skripte nicht umbenennen will, habe ich "kryptische" Links angelegt, die auf meine Skripte mit sprechendem Namen zeigen. [..] Leider liefert basename/dirname nicht den Namen des echten Skriptes sondern den des Links wenn die Teile unter dem Linknamen gestartet werden.
Kann man irgendwie elegant das ganze lösen?
AFAIK nicht "ootb", aber vielleicht hilft dir readlink zusammen mit test -f / test -L ... ==== minimal getestet ==== #! /bin/sh find_real_name() { if test -L "$1" then p="$1" while test -L "$p" do d="`dirname \"$p\"`" test -d "$d" && cd "$d" || exit 1 p="`basename \"$p\"`" test -L "$p" && { r="`readlink \"$p\"`" || exit 2; } p="`pwd`/$r" done fi d="`dirname \"$p\"`" test -d "$d" && cd "$d" || exit 3 p="`basename \"$p\"`" rn="`pwd`/$p" echo "$rn" } IAM="$0" IAM="`find_real_name \"$IAM\"`" echo "IAM='$IAM'" ==== ISTR, dass die mk* Tools von tex/web2c auch sowas (anders) machen... Schau dazu in $TEXMFROOT/teTeX/.../bin und /var/lib/texmf/web2c
(Keine Bastellösung der Art: mach mal ein ls und schau, ob es ein link es, wenn ja, ...)
Obiges ist ja sowas aehliches...
Auch eine Antwort "geht nicht, du musst basteln" ist OK (Das Basteln mache ich dann schon selber!)
Du koenntest evtl. auch den Pfad ins script schreiben... HTH, -dnh --
Ich dachte immer, WoKos hätten eine Menge Augen, ringsrum? Das muss aber nicht jeder wissen. es reicht doch schon wenn Ich das selbst nicht weiss. [Roland Jacob und WoKo in dag°]
![](https://seccdn.libravatar.org/avatar/735ea797d876adb026ae955e8adbf597.jpg?s=120&d=mm&r=g)
Am Donnerstag, 18. September 2003 19:00 schrieb David Haller:
Hallo,
Am Thu, 18 Sep 2003, Andreas Kyek schrieb:
Ich suche eine Lösung zu folgendem Problem:
[..]
Da ich meine eigentlichen Skripte nicht umbenennen will, habe ich "kryptische" Links angelegt, die auf meine Skripte mit sprechendem Namen zeigen.
[..]
Leider liefert basename/dirname nicht den Namen des echten Skriptes sondern den des Links wenn die Teile unter dem Linknamen gestartet werden.
Kann man irgendwie elegant das ganze lösen?
AFAIK nicht "ootb", aber vielleicht hilft dir readlink zusammen mit test -f / test -L ...
==== minimal getestet ==== #! /bin/sh
find_real_name() { if test -L "$1" then p="$1" while test -L "$p" do d="`dirname \"$p\"`" test -d "$d" && cd "$d" || exit 1 p="`basename \"$p\"`" test -L "$p" && { r="`readlink \"$p\"`" || exit 2; } p="`pwd`/$r" done fi d="`dirname \"$p\"`" test -d "$d" && cd "$d" || exit 3 p="`basename \"$p\"`" rn="`pwd`/$p" echo "$rn" }
IAM="$0" IAM="`find_real_name \"$IAM\"`"
echo "IAM='$IAM'"
Das sieht mir schon wieder recht kompliziert aus ;) ich="$0" while -n "`readlink \"$ich\"`"; do ich="`readlink \"$ich\"`" done echo "ich bin $ich" (ungetestet) Jan
![](https://seccdn.libravatar.org/avatar/735ea797d876adb026ae955e8adbf597.jpg?s=120&d=mm&r=g)
Am Donnerstag, 18. September 2003 23:08 schrieb Jan Trippler:
Am Donnerstag, 18. September 2003 19:00 schrieb David Haller:
Hallo,
Am Thu, 18 Sep 2003, Andreas Kyek schrieb:
Ich suche eine Lösung zu folgendem Problem:
[..]
Da ich meine eigentlichen Skripte nicht umbenennen will, habe ich "kryptische" Links angelegt, die auf meine Skripte mit sprechendem Namen zeigen.
[..]
Leider liefert basename/dirname nicht den Namen des echten Skriptes sondern den des Links wenn die Teile unter dem Linknamen gestartet werden.
Kann man irgendwie elegant das ganze lösen?
AFAIK nicht "ootb", aber vielleicht hilft dir readlink zusammen mit test -f / test -L ...
==== minimal getestet ==== #! /bin/sh
find_real_name() { if test -L "$1" then p="$1" while test -L "$p" do d="`dirname \"$p\"`" test -d "$d" && cd "$d" || exit 1 p="`basename \"$p\"`" test -L "$p" && { r="`readlink \"$p\"`" || exit 2; } p="`pwd`/$r" done fi d="`dirname \"$p\"`" test -d "$d" && cd "$d" || exit 3 p="`basename \"$p\"`" rn="`pwd`/$p" echo "$rn" }
IAM="$0" IAM="`find_real_name \"$IAM\"`"
echo "IAM='$IAM'"
Das sieht mir schon wieder recht kompliziert aus ;) ich="$0" while -n "`readlink \"$ich\"`"; do ich="`readlink \"$ich\"`" done echo "ich bin $ich"
(ungetestet)
Ja, und bei näherem Nachdenken ist mir tatsächlich eingefallen, warum Du es so kompliziert machst - relative Links in andere Verzeichnisse ;) Aber vielleicht gehts so: ich="$0" p="`pwd`" while test -n "`readlink \"$ich\"`"; do d="`dirname \"$ich\"`" test -n "$d" && cd "$d" || exit 1 ich="`readlink \"\`basename \"$ich\"\`\"`" done cd "$p" echo "ich bin $ich" (ein bisschen getestet) Jan
![](https://seccdn.libravatar.org/avatar/735ea797d876adb026ae955e8adbf597.jpg?s=120&d=mm&r=g)
Am Freitag, 19. September 2003 00:07 schrieb Jan Trippler: [...]
Aber vielleicht gehts so: ich="$0" p="`pwd`" while test -n "`readlink \"$ich\"`"; do d="`dirname \"$ich\"`" test -n "$d" && cd "$d" || exit 1 ich="`readlink \"\`basename \"$ich\"\`\"`" done cd "$p" echo "ich bin $ich"
(ein bisschen getestet)
Einen hab ich noch - Der engültige Wert von $ich steht natürlich in Bezug auf das letzte besuchte Verzeichnis, also muss ich noch ne Zeile einfügen, um diesen Bezug mitzuliefern (auch wenn es mir in der Seele weh tut ;) ich="$0" p="`pwd`" while test -n "`readlink \"$ich\"`"; do d="`dirname \"$ich\"`" test -n "$d" && cd "$d" || exit 1 ich="`readlink \"\`basename \"$ich\"\`\"`" done # dies ergaenzen: ich="`pwd`/\`basename \"$ich\"\``" cd "$p" echo "ich bin $ich" Jan
![](https://seccdn.libravatar.org/avatar/7b33cb1e776e35b87edb8ef09f0c888f.jpg?s=120&d=mm&r=g)
Hallo, Am Fri, 19 Sep 2003, Jan Trippler schrieb:
Einen hab ich noch - Der engültige Wert von $ich steht natürlich in Bezug auf das letzte besuchte Verzeichnis, also muss ich noch ne Zeile einfügen, um diesen Bezug mitzuliefern (auch wenn es mir in der Seele weh tut ;)
ich="$0" p="`pwd`" while test -n "`readlink \"$ich\"`"; do d="`dirname \"$ich\"`" test -n "$d" && cd "$d" || exit 1 ich="`readlink \"\`basename \"$ich\"\`\"`" done # dies ergaenzen: ich="`pwd`/\`basename \"$ich\"\``" cd "$p" echo "ich bin $ich"
Sorry, *moep*: ./usr/bin/foo.sh: line 55: unexpected EOF while looking for matching ``' ./usr/bin/foo.sh: line 58: syntax error: unexpected end of file Nach einer Korrektur zu: # dies ergaenzen: ich="`pwd`/`basename \"$ich\"`" dh@slarty[4]: /tmp/test4 (0)$ ./test_foo.sh | grep '^Jan3' Jan3: ich bin /tmp/test4/foo.sh [..] Jan3: ich bin /tmp/test4/foo.sh Jan3: ich bin /tmp/test4/usr/bin/foo.sh Jan3: ich bin /tmp/test4/usr/local/bin/foo.sh Jan3: ich bin /tmp/test4/opt/bin/foo.sh Jan3: ich bin /tmp/test4/opt/blubb/bin/foo.sh -dnh, apropos meine sig: wo ist Philipp eigentlich? -- [ls?] command not found? [..] Das ist ein kleiner Ludwig, gefolgt von einem kleinen Siegfried (zwei muntere Recken, die auszogen, den Drachen zu schrecken). Keine Ida, denn Burgfräulein haben in Heldenrunden nix verloren. Mach einfach mal nur ls (Ludwig-Siegfried, nicht Ida-Siegfried, das könnte unanständig werden *g*), [..] -- Philipp Zacharias in suse-linux
![](https://seccdn.libravatar.org/avatar/735ea797d876adb026ae955e8adbf597.jpg?s=120&d=mm&r=g)
Am Freitag, 19. September 2003 01:30 schrieb David Haller:
Am Fri, 19 Sep 2003, Jan Trippler schrieb: [...]
ich="$0" p="`pwd`" while test -n "`readlink \"$ich\"`"; do d="`dirname \"$ich\"`" test -n "$d" && cd "$d" || exit 1 ich="`readlink \"\`basename \"$ich\"\`\"`" done # dies ergaenzen: ich="`pwd`/\`basename \"$ich\"\``" cd "$p" echo "ich bin $ich"
Sorry, *moep*:
./usr/bin/foo.sh: line 55: unexpected EOF while looking for matching ``' ./usr/bin/foo.sh: line 58: syntax error: unexpected end of file
Jaja, es war spät und ich habe die letzte Änderung nicht mehr getestet ;)
Nach einer Korrektur zu:
# dies ergaenzen: ich="`pwd`/`basename \"$ich\"`"
dh@slarty[4]: /tmp/test4 (0)$ ./test_foo.sh | grep '^Jan3' Jan3: ich bin /tmp/test4/foo.sh [..]
Hm, ist das nun gut oder schlecht? Da ich Deine Links nicht kenne ... Ich nehme mal an schlecht, weil Du nun absolute Pfadnamen verwendest. Da muss man tatsächlich noch 2 Zeilen ergänzen (ich habe das Ganze mal in ein kleines Script verpackt, dem man den Namen des aufzulösenden Links mitgibt): <getlink.sh> ich="$1" p="`pwd`" while test -n "`readlink \"$ich\"`"; do d="`dirname \"$ich\"`" test -n "$d" && cd "$d" || exit 1 ich="`readlink \"\`basename \"$ich\"\`\"`" done d="`dirname \"$ich\"`" test -n "$d" && cd "$d" || exit 1 ich="`pwd`/`basename \"$ich\"`" cd "$p" echo "ich bin $ich" </getlink.sh> Ich habs mal kurz mit verschiedenen Kombinationen (Kette aus absoluten und relativen Pfaden mit und ohne Verzeichnisangabe) getestet, sah mir sauber aus. Jan
![](https://seccdn.libravatar.org/avatar/7b33cb1e776e35b87edb8ef09f0c888f.jpg?s=120&d=mm&r=g)
Hallo, Am Fri, 19 Sep 2003, Jan Trippler schrieb:
Am Freitag, 19. September 2003 01:30 schrieb David Haller:
Am Fri, 19 Sep 2003, Jan Trippler schrieb: dh@slarty[4]: /tmp/test4 (0)$ ./test_foo.sh | grep '^Jan3' Jan3: ich bin /tmp/test4/foo.sh [..]
Hm, ist das nun gut oder schlecht? Da ich Deine Links nicht kenne ...
Ich hatte das "find" schon gemailt. Das script selbst ist '/tmp/test4/opt/blubb/bin/foo.sh'... Da fehlt quasi ein cd ins dirname des letzten symlinks...
Ich nehme mal an schlecht, weil Du nun absolute Pfadnamen verwendest. Da muss man tatsächlich noch 2 Zeilen ergänzen (ich habe das Ganze mal in ein kleines Script verpackt, dem man den Namen des aufzulösenden Links mitgibt):
<getlink.sh> ich="$1" p="`pwd`" while test -n "`readlink \"$ich\"`"; do d="`dirname \"$ich\"`" test -n "$d" && cd "$d" || exit 1 ich="`readlink \"\`basename \"$ich\"\`\"`" done d="`dirname \"$ich\"`" test -n "$d" && cd "$d" || exit 1 ich="`pwd`/`basename \"$ich\"`" cd "$p" echo "ich bin $ich" </getlink.sh>
Ich habs mal kurz mit verschiedenen Kombinationen (Kette aus absoluten und relativen Pfaden mit und ohne Verzeichnisangabe) getestet, sah mir sauber aus.
Jup. Find ich gut, dass du letztlich doch die gleiche Loesung wie ich gefunden hast :) Zumindest in meinem Testfall liefert das jetzt auch die richtige Loesung... Und nun vergleiche das mal (modulo Variablennamen und Schleifenbedingung und Verpackung in eine Funktion sowie extra ``-Verschachtelung) mit meiner Version... Da ich ja eine Funktion verwende ist es auch nicht noetig, sich `pwd` zu merken. Ok, bei mir kommt noch das 'if' dazu, das, wie ich sehe ueberfluessig ist. Hier nochmal meine Version zum Vergleich: ==== find_real_name() { p="$1" while test -L "$p" do d="`dirname \"$p\"`" test -d "$d" && cd "$d" || exit 1 p="`basename \"$p\"`" test -L "$p" && { r="`readlink \"$p\"`" || exit 2; } p="`pwd`/$r" done d="`dirname \"$p\"`" test -d "$d" && cd "$d" || exit 1 p="`basename \"$p\"`" rn="`pwd`/$p" echo "$rn" } ==== Hm. Ich ueberlege gerade, warum ich am Ende des while 'p="`pwd`/$r"' verwende (mal abgesehen von der Hilfsvariablen $r)... IIRC, hab ich nen guten Grund... ;) -dnh -- 167: DAU Leute, die sich beim Falschparken selbst anzeigen. (Dietz Proepper)
![](https://seccdn.libravatar.org/avatar/7b33cb1e776e35b87edb8ef09f0c888f.jpg?s=120&d=mm&r=g)
Hallo, Am Fri, 19 Sep 2003, Jan Trippler schrieb:
Am Donnerstag, 18. September 2003 23:08 schrieb Jan Trippler: [..]
(ungetestet)
Ja, und bei näherem Nachdenken ist mir tatsächlich eingefallen, warum Du es so kompliziert machst - relative Links in andere Verzeichnisse ;)
Aber vielleicht gehts so: ich="$0" p="`pwd`" while test -n "`readlink \"$ich\"`"; do d="`dirname \"$ich\"`" test -n "$d" && cd "$d" || exit 1 ich="`readlink \"\`basename \"$ich\"\`\"`" done cd "$p" echo "ich bin $ich"
(ein bisschen getestet)
dh@slarty[4]: /tmp/test4 (0)$ sed -n '/^##/,$p' < ./usr/bin/foo.sh ### End DH ### Jan 1 ich="$0" while test -n "`readlink \"$ich\"`"; do ich="`readlink \"$ich\"`" done echo "ich bin $ich" ### Jan 2 ich="$0" p="`pwd`" while test -n "`readlink \"$ich\"`"; do d="`dirname \"$ich\"`" test -n "$d" && cd "$d" || exit 1 ich="`readlink \"\`basename \"$ich\"\`\"`" done cd "$p" echo "Jan2: ich bin $ich" dh@slarty[4]: /tmp/test4 (0)$ ./usr/bin/foo.sh IAM='/tmp/test4/opt/blubb/bin/foo.sh' ich bin ../local/bin/foo.sh Jan2: ich bin ../blubb/bin/foo.sh dh@slarty[4]: /tmp/test4 (0)$ Fast. Ich mach ja fast das gleiche, nur mit mehr Variablen und checks, ob's noch ein symlink ist und das ganze in eine Funktion verpackt... Bei dir fehlt dann noch das Aufloesen des letzten relativen links... Ausserdem habe ich bei deiner Version noch ein ungutes Gefuehl wg. der Schleifenbedingung. Aber meine Version hat(te) auch noch nen "Bug": Wenn das script direkt, und nicht via symlink aufgerufen wurden, waere "IAM=`pwd`" (egal wo `pwd` ist). Durch das Verschieben der Zuweisung p="$1" vor das 'if test -L' ist dieser Bug behoben: ==== find_real_name() { p="$1" # ! if test -L "$1" then # ! while test -L "$p" do d="`dirname \"$p\"`" test -d "$d" && cd "$d" || exit 1 p="`basename \"$p\"`" test -L "$p" && { r="`readlink \"$p\"`" || exit 2; } p="`pwd`/$r" done fi d="`dirname \"$p\"`" test -d "$d" && cd "$d" || exit 1 p="`basename \"$p\"`" rn="`pwd`/$p" echo "$rn" } ==== Ja, evtl. koenne man da noch mehr pro Zeile verschachteln, aber ist das sinnvoll? Oh, und da faellt mir ein, alle Versionen sollten einen Zaehler gegen symlink-loops haben... Naja, ich hab grad mal eine loop gebaut: lrwxrwxrwx 19 ./usr/bin/foo.sh -> ../local/bin/foo.sh lrwxrwxrwx 23 ./usr/local/bin/foo.sh -> ../../../opt/bin/foo.sh lrwxrwxrwx 20 ./opt/bin/foo.sh -> ../../usr/bin/foo.sh Und das script bricht ab mit: bash: ./usr/bin/foo.sh: Too many levels of symbolic links Also ist wohl nicht noetig ;) -dnh -- 18: Vorbereitet für den Multimediaeinsatz Es sind noch zwei Slots auf dem Motherboard frei. (Peter Berlich)
![](https://seccdn.libravatar.org/avatar/735ea797d876adb026ae955e8adbf597.jpg?s=120&d=mm&r=g)
Am Freitag, 19. September 2003 01:08 schrieb David Haller: [...]
Fast. Ich mach ja fast das gleiche, nur mit mehr Variablen und checks, ob's noch ein symlink ist und das ganze in eine Funktion verpackt... Bei dir fehlt dann noch das Aufloesen des letzten relativen links...
Ausserdem habe ich bei deiner Version noch ein ungutes Gefuehl wg. der Schleifenbedingung.
Warum? Deshalb fiel mir ja Deine Variante auf, sie prüft etwas, was readlink schon selbst macht, nämlich prüfen, ob der angegebene Pfad ein symbolischer Link ist. Wenn es keiner ist, kommt "" zurück - warum sollte man das nicht nutzen? Jan
![](https://seccdn.libravatar.org/avatar/7b33cb1e776e35b87edb8ef09f0c888f.jpg?s=120&d=mm&r=g)
Hallo, Am Fri, 19 Sep 2003, Jan Trippler schrieb:
Am Freitag, 19. September 2003 01:08 schrieb David Haller: [...]
Fast. Ich mach ja fast das gleiche, nur mit mehr Variablen und checks, ob's noch ein symlink ist und das ganze in eine Funktion verpackt... Bei dir fehlt dann noch das Aufloesen des letzten relativen links...
Ausserdem habe ich bei deiner Version noch ein ungutes Gefuehl wg. der Schleifenbedingung.
Warum? Deshalb fiel mir ja Deine Variante auf, sie prüft etwas, was readlink schon selbst macht, nämlich prüfen, ob der angegebene Pfad ein symbolischer Link ist. Wenn es keiner ist, kommt "" zurück - warum sollte man das nicht nutzen?
Auch wieder wahr ;) -dnh -- For every complex problem, there is a solution that is simple, neat, and wrong. -- H. L. Mencken
![](https://seccdn.libravatar.org/avatar/7b33cb1e776e35b87edb8ef09f0c888f.jpg?s=120&d=mm&r=g)
Hallo, Am Thu, 18 Sep 2003, Jan Trippler schrieb:
Am Donnerstag, 18. September 2003 19:00 schrieb David Haller:
Am Thu, 18 Sep 2003, Andreas Kyek schrieb: [..]
Leider liefert basename/dirname nicht den Namen des echten Skriptes sondern den des Links wenn die Teile unter dem Linknamen gestartet werden.
Kann man irgendwie elegant das ganze lösen?
AFAIK nicht "ootb", aber vielleicht hilft dir readlink zusammen mit test -f / test -L ...
==== minimal getestet ==== #! /bin/sh
find_real_name() { if test -L "$1" then p="$1" while test -L "$p" do d="`dirname \"$p\"`" test -d "$d" && cd "$d" || exit 1 p="`basename \"$p\"`" test -L "$p" && { r="`readlink \"$p\"`" || exit 2; } p="`pwd`/$r" done fi d="`dirname \"$p\"`" test -d "$d" && cd "$d" || exit 3 p="`basename \"$p\"`" rn="`pwd`/$p" echo "$rn" }
IAM="$0" IAM="`find_real_name \"$IAM\"`"
echo "IAM='$IAM'"
Das sieht mir schon wieder recht kompliziert aus ;) ich="$0" while -n "`readlink \"$ich\"`"; do ^^ da fehlt ein 'test ' ich="`readlink \"$ich\"`" done echo "ich bin $ich"
(ungetestet)
Schon mit relativen links getestet, ueber mehr als eine "Verlinkungsebene"??? *eg* ==== dh@slarty[4]: /tmp/test4 (0)$ tail ./usr/bin/foo.sh IAM="$0" IAM="`find_real_name \"$IAM\"`" echo "IAM='$IAM'" ich="$0" while test -n "`readlink \"$ich\"`"; do ich="`readlink \"$ich\"`" done echo "ich bin $ich" dh@slarty[4]: /tmp/test4 (0)$ find . -name "foo.sh" -ls \ | awk '{print $3" "$7"\t"$11" "$12" "$13;}' lrwxrwxrwx 19 ./usr/bin/foo.sh -> ../local/bin/foo.sh lrwxrwxrwx 23 ./usr/local/bin/foo.sh -> ../../../opt/bin/foo.sh lrwxrwxrwx 19 ./opt/bin/foo.sh -> ../blubb/bin/foo.sh -rwxr--r-- 624 ./opt/blubb/bin/foo.sh dh@slarty[4]: /tmp/test4 (0)$ ./usr/bin/foo.sh IAM='/tmp/test4/opt/blubb/bin/foo.sh' ich bin ../local/bin/foo.sh dh@slarty[4]: /tmp/test4 (0)$ PATH="./usr/bin:$PATH" foo.sh IAM='/tmp/test4/opt/blubb/bin/foo.sh' ich bin ../local/bin/foo.sh dh@slarty[4]: /tmp/test4 (0)$ PATH="./usr/local/bin:./usr/bin:$PATH" foo.sh IAM='/tmp/test4/opt/blubb/bin/foo.sh' ich bin ../../../opt/bin/foo.sh dh@slarty[4]: /tmp/test4 (0)$ `pwd`/usr/bin/foo.sh IAM='/tmp/test4/opt/blubb/bin/foo.sh' ich bin ../local/bin/foo.sh ==== Merkst du was, Jan? *scnr* Ja, manchmal verrenke/verkompliziere ich mich unnoetig, diesmal aber nicht... ;) Und nein, ich wage nicht zu behaupten, dass meine Version in allen Faellen das richtige Ergebnis liefert... -dnh PS: An alle die sich ueber das Quoting bei z.B. bei ich="`readlink \"$ich\"`" von Jan und mir wundern, das ist noetig und die einzig richtige Variante -- alle andere Varianten verrupft's bei Dateinamen mit entweder Leerzeichen oder mit shell-wildcards wie '*'. Wir beide haben das hier sogar schon vorexerziert. -- 144: Maxmimale Entfernung zweier Hubs 12800 km. (Roger Schwendker)
![](https://seccdn.libravatar.org/avatar/735ea797d876adb026ae955e8adbf597.jpg?s=120&d=mm&r=g)
Moin, Am Freitag, 19. September 2003 00:31 schrieb David Haller:
Am Thu, 18 Sep 2003, Jan Trippler schrieb: [...]
Das sieht mir schon wieder recht kompliziert aus ;) ich="$0" while -n "`readlink \"$ich\"`"; do
^^ da fehlt ein 'test '
ich="`readlink \"$ich\"`" done echo "ich bin $ich"
(ungetestet) ^^^^^^^^^^^^--------------------------------------------+ Schon mit relativen links getestet, ueber mehr als eine | "Verlinkungsebene"??? *eg* | siehe >----------------------------------------------------+
Das fiel mir später auch auf - siehe meine andere Mail. [...]
Merkst du was, Jan? *scnr*
Schon passiert ;)
Ja, manchmal verrenke/verkompliziere ich mich unnoetig, diesmal aber nicht... ;)
Na, mal sehen *g* Jan
![](https://seccdn.libravatar.org/avatar/7b33cb1e776e35b87edb8ef09f0c888f.jpg?s=120&d=mm&r=g)
Hallo, Am Fri, 19 Sep 2003, Jan Trippler schrieb:
Am Freitag, 19. September 2003 00:31 schrieb David Haller:
Am Thu, 18 Sep 2003, Jan Trippler schrieb: [...]
Das sieht mir schon wieder recht kompliziert aus ;) ich="$0" while -n "`readlink \"$ich\"`"; do
^^ da fehlt ein 'test '
ich="`readlink \"$ich\"`" done echo "ich bin $ich"
(ungetestet) ^^^^^^^^^^^^--------------------------------------------+ Schon mit relativen links getestet, ueber mehr als eine | "Verlinkungsebene"??? *eg* | siehe >----------------------------------------------------+
Das fiel mir später auch auf - siehe meine andere Mail.
*hihi*
[...]
Merkst du was, Jan? *scnr*
Schon passiert ;)
Ja, manchmal verrenke/verkompliziere ich mich unnoetig, diesmal aber nicht... ;)
Na, mal sehen *g*
Ok. Du hast es so gewollt... ==== /tmp/test4/test_foo.sh ==== #! /bin/bash for t in \ ./usr/bin/foo.sh \ ./usr/local/bin/foo.sh \ ./opt/bin/foo.sh \ ./opt/blubb/bin/foo.sh \ /tmp/test4/usr/bin/foo.sh \ /tmp/test4/usr/local/bin/foo.sh \ /tmp/test4/opt/bin/foo.sh \ /tmp/test4/opt/blubb/bin/foo.sh \ 'PATH="./usr/bin:$PATH" foo.sh' \ 'PATH="./usr/local/bin:$PATH" foo.sh' \ 'PATH="./usr/bin:./usr/local/bin:$PATH" foo.sh' \ 'PATH="./usr/local/bin:./usr/bin:$PATH" foo.sh' \ 'PATH="./opt/bin:$PATH" foo.sh' \ 'PATH="./opt/blubb/bin:$PATH" foo.sh' \ 'PATH="`pwd`/opt/bin:$PATH" foo.sh' \ 'PATH="`pwd`/opt/blubb/bin:$PATH" foo.sh' \ "cd ./usr/bin && ./foo.sh; cd -;" \ "cd ./usr/local/bin && ./foo.sh; cd -;" \ "cd ./opt/bin && ./foo.sh; cd -;" \ "cd ./opt/blubb/bin && ./foo.sh; cd -;" do echo "+ '$t'" eval "$t" echo done ==== dh@slarty[4]: /tmp/test4 (0)$ find . -name "foo.sh" -ls \ | awk '{print $3" "$7"\t"$11" "$12" "$13;}' lrwxrwxrwx 19 ./usr/bin/foo.sh -> ../local/bin/foo.sh lrwxrwxrwx 23 ./usr/local/bin/foo.sh -> ../../../opt/bin/foo.sh lrwxrwxrwx 19 ./opt/bin/foo.sh -> ../blubb/bin/foo.sh -rwxr--r-- 1112 ./opt/blubb/bin/foo.sh ==== /tmp/test4/opt/blubb/bin/foo.sh ==== #! /bin/sh find_real_name() { p="$1" if test -L "$1" then while test -L "$p" do d="`dirname \"$p\"`" test -d "$d" && cd "$d" || exit 1 p="`basename \"$p\"`" test -L "$p" && { r="`readlink \"$p\"`" || exit 2; } p="`pwd`/$r" done fi d="`dirname \"$p\"`" test -d "$d" && cd "$d" || exit 1 p="`basename \"$p\"`" rn="`pwd`/$p" echo "$rn" } IAM="$0" IAM="`find_real_name \"$IAM\"`" echo "IAM='$IAM'" ### End DH ### Jan 1 ich="$0" while test -n "`readlink \"$ich\"`"; do ich="`readlink \"$ich\"`" done echo "Jan1: ich bin $ich" ### Jan 2 ich="$0" p="`pwd`" while test -n "`readlink \"$ich\"`"; do d="`dirname \"$ich\"`" test -n "$d" && cd "$d" || exit 1 ich="`readlink \"\`basename \"$ich\"\`\"`" done cd "$p" echo "Jan2: ich bin $ich" ### Jan 3 p="`pwd`" while test -n "`readlink \"$ich\"`"; do d="`dirname \"$ich\"`" test -n "$d" && cd "$d" || exit 1 ich="`readlink \"\`basename \"$ich\"\`\"`" done # dies ergaenzen: ich="`pwd`/`basename \"$ich\"`" cd "$p" echo "Jan3: ich bin $ich" ==== Lass mal in /tmp/test4 "./test_foo.sh" durchlaufen... Achso, meine erste Version lieferte immerhin in 15/20 Faellen das richtige Ergebnis... -dn'*scnr*'h -- Wer heiratet kann Sorgen teilen, die er vorher nicht hatte.
![](https://seccdn.libravatar.org/avatar/ebe9e7470f033d101415722d029f0b24.jpg?s=120&d=mm&r=g)
Andreas Kyek <a.kyek@vodafone.com>:
Leider liefert basename/dirname nicht den Namen des echten Skriptes sondern den des Links wenn die Teile unter dem Linknamen gestartet werden.
Jan.Trippler@t-online.de (Jan Trippler)
Das sieht mir schon wieder recht kompliziert aus ;) ich="$0" while -n "`readlink \"$ich\"`"; do ich="`readlink \"$ich\"`" done echo "ich bin $ich"
es geht anscheinend noch einfacher:
readlink --help Usage: readlink [OPTION]... FILE Display value of a symbolic link on standard output.
-f, --canonicalize canonicalize by following every symlink in every component of the given path recursively Bye Jürgen -- Dr.rer.nat. Juergen Vollmer, Viktoriastrasse 15, D-76133 Karlsruhe Tel: +49(721) 9204871 Fax: +49(721) 24874 Juergen.Vollmer@[informatik-vollmer.de|alumni.uni-karlsruhe.de|acm.org] www.informatik-vollmer.de
![](https://seccdn.libravatar.org/avatar/ffcbb0f1ce7068f1fde373b35ab383f4.jpg?s=120&d=mm&r=g)
On Friday 19 September 2003 08:37, Dr. Jürgen Vollmer wrote:
Andreas Kyek <a.kyek@vodafone.com>:
Leider liefert basename/dirname nicht den Namen des echten Skriptes sondern den des Links wenn die Teile unter dem Linknamen gestartet werden.
Jan.Trippler@t-online.de (Jan Trippler)
Das sieht mir schon wieder recht kompliziert aus ;) ich="$0" while -n "`readlink \"$ich\"`"; do ich="`readlink \"$ich\"`" done echo "ich bin $ich"
es geht anscheinend noch einfacher:
readlink --help
Usage: readlink [OPTION]... FILE Display value of a symbolic link on standard output.
-f, --canonicalize canonicalize by following every symlink in every component of the given path recursively
readlink wäre wohl schon 'ne schöne Lösung. Aber a) auf meiner Testmaschinen (SuSE 7.3) ist readlink wohl in Version readlink (kpathsea version 3.3.1) installiert. Das kennt die Option -f nicht. b) Viel schlimmer: Leider gibts das Teil wohl auf den betroffenen produktiven Maschinen nicht (sind grosse SUN Solaris Maschinen). Schade Andreas
![](https://seccdn.libravatar.org/avatar/ebe9e7470f033d101415722d029f0b24.jpg?s=120&d=mm&r=g)
Andreas Kyek <a.kyek@vodafone.com>
b) Viel schlimmer: Leider gibts das Teil wohl auf den betroffenen produktiven Maschinen nicht (sind grosse SUN Solaris Maschinen).
also bevor man die ganzen Shell-Lösungen probiert, würde ich a). einen Einzeiler in Perl versuchen (s. meine frühere email), oder b). die Quellen zu readlink besorgen und übersetzen oder c). selbst ein kleines C-Proggi schreiben: man 2 readlink ist dazu der entsprechende Aufruf. Das Proggi ist mehr oder wendiger ein "Einzeiler". Ok, dazu braucht's einen C-Compiler, und der ist ja bei Sun nicht immer dabei. Jürgen -- Dr.rer.nat. Juergen Vollmer, Viktoriastrasse 15, D-76133 Karlsruhe Tel: +49(721) 9204871 Fax: +49(721) 24874 Juergen.Vollmer@[informatik-vollmer.de|alumni.uni-karlsruhe.de|acm.org] www.informatik-vollmer.de
![](https://seccdn.libravatar.org/avatar/7b33cb1e776e35b87edb8ef09f0c888f.jpg?s=120&d=mm&r=g)
Hallo, Am Fri, 19 Sep 2003, Dr. Jürgen Vollmer schrieb:
Andreas Kyek <a.kyek@vodafone.com> [..]
Mein readlink kennt '-f' auch nicht.
b) Viel schlimmer: Leider gibts das Teil wohl auf den betroffenen produktiven Maschinen nicht (sind grosse SUN Solaris Maschinen).
also bevor man die ganzen Shell-Lösungen probiert, würde ich a). einen Einzeiler in Perl versuchen (s. meine frühere email), oder b). die Quellen zu readlink besorgen und übersetzen oder c). selbst ein kleines C-Proggi schreiben:
Naja, das 'readlink $name' kann man evtl. auf mehr Plattformen auch durch ls -l "$name" | awk '{print $NF;}' oder ein find "$name" -printf "%l" ersetzen (oder ist das "%l" schon wieder GNU find spezifisch?). -dnh -- [Re : quantum physics] "I can't say I care one way or another." -- Kai Henningsen "That's just because nobody's measured you yet." -- Christian Bauernfeind
![](https://seccdn.libravatar.org/avatar/735ea797d876adb026ae955e8adbf597.jpg?s=120&d=mm&r=g)
Am Freitag, 19. September 2003 14:53 schrieb David Haller:
Hallo,
Am Fri, 19 Sep 2003, Dr. Jürgen Vollmer schrieb:
Andreas Kyek <a.kyek@vodafone.com>
[..]
Mein readlink kennt '-f' auch nicht.
dito
also bevor man die ganzen Shell-Lösungen probiert, würde ich a). einen Einzeiler in Perl versuchen (s. meine frühere email), oder b). die Quellen zu readlink besorgen und übersetzen oder c). selbst ein kleines C-Proggi schreiben:
Im Prinzip ja, aber ein kleines Shell-Konstrukt kannst Du eben schnell in Dein vorhandenes Script einbauen, C-Compiler gibts nicht überall und Perl-Interpreter (seltener) auch nicht.
Naja, das 'readlink $name' kann man evtl. auf mehr Plattformen auch durch
ls -l "$name" | awk '{print $NF;}'
Nein: jan@roland:~/tmp> touch "l i n k" jan@roland:~/tmp> ln -s "l i n k" l jan@roland:~/tmp> ls -l l | awk '{print $NF}' k
oder ein
find "$name" -printf "%l"
ersetzen (oder ist das "%l" schon wieder GNU find spezifisch?).
Nicht der %l, sondern der printf ist GNU-spezifisch. Jan
![](https://seccdn.libravatar.org/avatar/7b33cb1e776e35b87edb8ef09f0c888f.jpg?s=120&d=mm&r=g)
Hallo, Am Fri, 19 Sep 2003, Jan Trippler schrieb:
Am Freitag, 19. September 2003 14:53 schrieb David Haller: [..]
Naja, das 'readlink $name' kann man evtl. auf mehr Plattformen auch durch
ls -l "$name" | awk '{print $NF;}'
Nein: jan@roland:~/tmp> touch "l i n k" jan@roland:~/tmp> ln -s "l i n k" l jan@roland:~/tmp> ls -l l | awk '{print $NF}' k
*autsch* stimmt. '| awk -F'>' '{print $2;}' sollte aber meist klappen. Bei Dateinamen wie 'C|N>K' geht das aber auch schief ;) Wie portable ist eigentlich -F<string>? z.B.: $ ln -s usr/bin/foo.sh './C|N>K' $ ls -l C\|N\>K | awk -F" -> " '{print $2;}' usr/bin/foo.sh Jaja, ich ahne es, das ist auch wieder ein GNUism. Hm. lt. der manpage... Mompl... Jep. Ist es. Das awk auf nem SunOS 5.8 kennt das nicht so, sondern interpretiert das wie IFS als Zeichenaufzaehlung.
oder ein
find "$name" -printf "%l"
ersetzen (oder ist das "%l" schon wieder GNU find spezifisch?).
Nicht der %l, sondern der printf ist GNU-spezifisch.
Stimmt. o.g. awk/SunOS/Solaris kennt das net. *boerks* Und wenn's dann noch nichtmal nen compiler gibt... (auf der Kiste, auf der ich testen kann gibt's zum Glueck einen). Faellt dir was ein, wie man readlink sonst ggfs. ersetzten koennte? -dnh -- Mal ne Nacht drueber schlafen ist bei Linux eine "gute Idee"[tm] ;) [David Haller in suse-linux]
![](https://seccdn.libravatar.org/avatar/735ea797d876adb026ae955e8adbf597.jpg?s=120&d=mm&r=g)
Am Freitag, 19. September 2003 22:14 schrieb David Haller: [...]
Faellt dir was ein, wie man readlink sonst ggfs. ersetzten koennte?
Ja, die Variante von Jürgen: C ;) Dann hat man gleich noch so nette Helferlein wie realpath() zur Verfügung, die das ständige cd (resp. chdir() in C) überflüssig machen. Und wenn man schon dabei ist, kann man auch gleich Link-Loops enttarnen ;) Das wird aber deutlich aufwändiger, wenn man es halbwegs sicher machen will und ist von der Ausgangsfragestellung (mal was schnelles) meilenweit entfernt. Jan
![](https://seccdn.libravatar.org/avatar/7b33cb1e776e35b87edb8ef09f0c888f.jpg?s=120&d=mm&r=g)
Hallo, Am Sat, 20 Sep 2003, Jan Trippler schrieb:
Am Freitag, 19. September 2003 22:14 schrieb David Haller: [...]
Faellt dir was ein, wie man readlink sonst ggfs. ersetzten koennte?
Ja, die Variante von Jürgen: C ;)
Ja. Haette schreiben sollen: "...ausser mit C"...
Dann hat man gleich noch so nette Helferlein wie realpath() zur
==== #if defined __USE_BSD || defined __USE_XOPEN_EXTENDED /* Return the canonical absolute name of file NAME. The last file name component need not exist, and may be a symlink to a nonexistent file. If RESOLVED is null, the result is malloc'd; otherwise, if the canonical name is PATH_MAX chars or more, returns null with `errno' set to ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars, returns the name in RESOLVED. */ extern char *realpath __P ((__const char *__restrict __name, char *__restrict __resolved)); #endif ==== Die manpages, die ich mir vom erwaehnten SunOS kopiert habe, kennen das jedenfalls nicht...
Verfügung, die das ständige cd (resp. chdir() in C) überflüssig machen. Und wenn man schon dabei ist, kann man auch gleich Link-Loops enttarnen ;)
*g*
Das wird aber deutlich aufwändiger, wenn man es halbwegs sicher machen will und ist von der Ausgangsfragestellung (mal was schnelles) meilenweit entfernt.
ACK. V.a. wenn's auch ohne C gehen soll. Ich denke, man kommt einfach um ein paar Vorraussetzungen nicht herum... "readlink(1kpathsea)" ist ja nun wirklich nur ein recht einfacher Wrapper um readlink(2)... -dnh -- Effekt: der neu gebaute ld.so kippt mit einer Assertion Failure aus den Latschen. Die glibc-Leute sind wirklich zu blöd zum Kacken. Glücklicherweise bricht das Teil unter seinem Eigengewicht zusammen, bevor es sich systemweit über relevante Verzeichnisse ergossen hat. -- fefe in dasr
![](https://seccdn.libravatar.org/avatar/440955ab796fb403fba608d0df23b654.jpg?s=120&d=mm&r=g)
Hallo David, hallo Jan, hallo Leute, (sorry für die Verspätung!) Am Freitag, 19. September 2003 22:14 schrieb David Haller: [Symlinks auflösen]
Faellt dir was ein, wie man readlink sonst ggfs. ersetzten koennte?
perl -e 'use Cwd "abs_path"; print abs_path("dir/dir/bild.png");' ^^^^^^^^^^^^^^^^ Pfad und Dateiname natürlich entsprechend ersetzen ;-) Fragt mich aber bitte nicht, wie Perl das intern macht. Das ist ggf. im entsprechenden Perlmodul nachzulesen ;-) Gruß Christian Boltz --
Ich hab letztens nen Film gesehen, in dem sich zwei Irre unterhalten haben. Da hat der eine den anderen auch nicht verstanden. Stimmt, hast Recht. Wann haben wir übrigens wieder Freigang? ;) [> Martin Borchert und Bernd Brodesser in suse-linux]
![](https://seccdn.libravatar.org/avatar/735ea797d876adb026ae955e8adbf597.jpg?s=120&d=mm&r=g)
Am Sonntag, 28. September 2003 20:52 schrieb Christian Boltz: [...]
perl -e 'use Cwd "abs_path"; print abs_path("dir/dir/bild.png");' ^^^^^^^^^^^^^^^^ Pfad und Dateiname natürlich entsprechend ersetzen ;-)
Fragt mich aber bitte nicht, wie Perl das intern macht. Das ist ggf. im entsprechenden Perlmodul nachzulesen ;-)
Es gibt eine Bibliotheksfunktion realpath(). Vielleicht damit? Mich wundert eh, dass noch niemand dafür ein Kommandozeilentool geschrieben hat (oder kenne ich es bloß noch nicht?) Jan
participants (5)
-
Andreas Kyek
-
Christian Boltz
-
David Haller
-
Dr. Jürgen Vollmer
-
Jan.Trippler@t-online.de