Ich habe ein Skript (~/.../gremlin), für das ich einen Softlink erstellt habe:
ln -s ~/[...]/gremlin ~/sc/gremlin
~/sc/gremlin
ist in $PATH
.
Der direkte Aufruf des Skripts funktioniert.
Der Aufruf über den Link funktioniert nicht.
Es verwendet dirname $0
, sodass es nichts erhält.
Gibt es eine Möglichkeit, dieses Setup zum Laufen zu bringen, ohne das Skript zu ändern und ohne anstelle des Softlinks ein weiteres zu erstellen?
So wird $0 verwendet:
case `uname` in
CYGWIN*)
CP=$( echo `dirname $0`/../lib/*.jar . | sed 's/ /;/g')
;;
*)
CP=$( echo `dirname $0`/../lib/*.jar . | sed 's/ /:/g')
esac
Antwort1
Ob die Verwendung von dirname $0
ein Problem darstellt oder nicht, hängt davon ab,Wiees wird verwendet. Ohne weitere Details können wir das nicht beantworten.
Wenn (a) die Verwendung dirname $0
ein Problem darstellt und (b) Sie das Skript nicht ändern können, besteht die Lösung darin, den Softlink ~/sc/gremlin
durch ein Skript zu ersetzen:
#!/bin/sh
exec ~/../gremlin "$@"
Auf diese Weise ~/../gremlin
wird ein korrekter ausgeführt $0
.
Die Verwendung von exec
bedeutet, dass der Prozess, der das Skript ausführt, ~/../gremlin
den Prozess ersetzt, der ausgeführt wird ~/sc/gremlin
. Dies ist effizienter, als beide Prozesse bis zum ~/../gremlin
Abschluss beizubehalten.
Antwort2
~/...
Wenn Sie das Verzeichnis nicht aus dem Skript heraus $0
, sondern von ableiten möchten ~/sc
, haben Sie folgende Möglichkeiten:
Wenn es ein zsh
Skript ist:
#! /bin/zsh -
dir=$0:A:h
Andernfalls und vorausgesetzt, Sie haben einen readlink
Befehl, der sich wie der von GNU verhält (einige Systeme haben einen realpath
Befehl, den Sie möglicherweise stattdessen verwenden können):
#! /bin/sh -
dir=$(dirname -- "$(readlink -f -- "$0")")
readlink -f
und $0:A
gebe Ihnen diekanonischPfad der Datei, d. h. ein absoluter Pfad nach Auflösung aller symbolischen Links in allen Pfadkomponenten.
Und dann:
set -- "$dir"/../lib/*.jar .
case $(uname) in
CYGWIN*) IFS=';';;
*) IFS=:;;
esac
CP="$*"
Oder:
case $(uname) in
CYGWIN*) sep=';';;
*) sep=:;;
esac
CP=$(printf "%s$sep" "$dir"/../lib/*.jar).
Antwort3
Wie @john1024 anmerkte, könnte der Tippfehler in der Frage des OP der Kern der Frage sein:
ln -s ~/.../gremlin ~/sc/gremlin
Während einige Anwendungen dreifache Punkte akzeptieren, ist dies bei Unix-Dateisystemen nicht der Fall.Hülseerweitert die ~
(Tilde), nicht ln
, also
ln -s ~/../gremlin ~/sc/gremlin
würde den Pfadnamen wie erwartet erweitern. Wenn der Link bereits existiert, können Sie ihn mit der -f
Option überschreiben. Wenn das Ziel jedoch eine tatsächliche Datei ist, -f
überschreibt die Option die Datei stillschweigend mit einem symbolischen Link. Vielleicht möchten Sie die -i
Option verwenden, die Ihnen zumindest mitteilt, dass bereits etwas vorhanden ist.
Wenn Sie den Link validieren möchten (nachweisen möchten, dass er auf eine Datei verweist), ist die -L
folgende Option ls
hilfreich:
ls -lL ~/sc/gremlin
Wenn es sich nicht um eine Datei handelt, ls
wird (je nach Implementierung) nur ein l
für den Typ (das erste Zeichen der Auflistung) mit Fragezeichen für die Berechtigungsbits oder ein anderer Hinweis angezeigt, der darauf hinweist, dass es sich nicht um eine echte Datei handelt (OSX weigert sich in diesem Fall einfach, überhaupt etwas anzuzeigen, obwohl es die Größe des symbolischen Links in die Gesamtsumme einbezieht).
Weiterführende Literatur:
- Dreifache Punkt-Platzhalter
- Was ist aus der Möglichkeit geworden, mit … (drei Punkte) auf das Großelternverzeichnis zu verweisen?
- 4.5.1 Auslassungspunkte als Platzhalterzeichen(ein Feature von VMS aus den 1980er Jahren)