Warum ist $0=/bin/foo, wenn /bin ein symbolischer Link ist?

Warum ist $0=/bin/foo, wenn /bin ein symbolischer Link ist?

Ich habe meine Bash-Skripte installiert /usr/bin/app.shund/usr/bin/lib.sh

app.shbeinhaltet

source "/usr/bin/lib.sh"

und lib.shbeinhaltet

if [ "/usr/bin/app.sh" == "$0"] ...

Wenn ich es app.shvon der Shell aus ausführe, schlägt dieser Test fehl, weil $0es sich tatsächlich um einen symbolischen Link handelt /bin/app.sh. Auf dem Dateisystem /binbefindet sich ein symbolischer Link zu/usr/bin

Wie kann man am besten feststellen, ob es von (im Gegensatz zu ) lib.sheingeschlossen wird, und zwar so, dass es nicht von der Umgebung ausgetrickst wird? Ich hätte gedacht, dass absolute Pfade ohne symbolische Links den Job erledigen würden, aber das ist anscheinend nicht der Fall.app.shother-app.sh

Antwort1

Um zu überprüfen, ob zwei Dateien gleich sind, müssen Sie die Indexnummer (Inode) überprüfen, die wie folgt angezeigt wird:

stat -L -c %i FilePath

Ihr Scheck lautet jetzt:

if [ $(stat -L -c %i "/usr/bin/app.sh") == $(stat -L -c %i "$0") ] ...

Dies funktioniert unabhängig von etwaigen Links im Verzeichnispfad oder sogar einem symbolischen oder Hardlink zur Datei selbst.

Um ganz genau zu sein (danke an @ilkkachu für den Hinweis), ist es sehr unwahrscheinlich, dass zwei verschiedene Dateien mit demselben Namen denselben Inode auf zwei verschiedenen Dateisystemen haben. Um dies zu vermeiden, schließen Sie die Gerätenummer in den Vergleich ein:

if [ $(stat -L -c %d:%i "/usr/bin/app.sh") == $(stat -L -c %d:%i "$0") ] ...

Antwort2

readlink -f /path/to/whateverteilt Ihnen den kanonischen Pfad mit (der /usr/bin/app.shin Ihrem Beispiel der Fall sein wird).

Ausdie Manpage:

kanonisieren, indem jedem Symlink in jeder Komponente des angegebenen Namens rekursiv gefolgt wird; alle Komponenten außer der letzten müssen vorhanden sein

verwandte Informationen