Wie kann ich den absoluten Dateinamen in einem Shell-Skript unter Mac OS X abrufen?

19

Ich möchte den absoluten Dateinamen der aktuell ausgeführten Skriptdatei abrufen. Links sollten auch aufgelöst werden.

Unter Linux scheint das so zu sein:

$(readlink -mn "$0")

readlinkscheint aber unter Mac OS X ganz anders zu funktionieren.

Ich habe gelesen, dass dies mit getan wird

$(realpath $0)

in BSD funktioniert das aber auch nicht. Mac OS X hat nicht realpath.

Irgendeine Idee?

Huxi
quelle
1
Siehe diese Frage auf SO: stackoverflow.com/questions/799679/…
Telemachus
3
Und das hier: stackoverflow.com/questions/1055671/…
Telemachus
Noch mehr Optionen: stackoverflow.com/questions/7665/…
Gerhard Burger

Antworten:

19

Ich betrüge und benutze Perl für genau das:

#!/bin/bash
dirname=`perl -e 'use Cwd "abs_path";print abs_path(shift)' $0`
echo $dirname

Man könnte meinen, ich würde nur das gesamte Skript in Perl schreiben, und das tue ich oft, aber nicht immer.

ericslaw
quelle
Das funktioniert, vielen Dank. Ich gebe dir eine Gegenstimme, sobald ich kann. Hat jemand eine "pure Shell" -Methode, um dies zu tun?
Huxi
1
Ich fürchte, das ist so gut wie es nur geht. (Angesichts der vielen mehrzeiligen "Pure Shell" -Hacks, die man bei Google finden kann.)
Arjan
Eine andere (wenn auch hässliche) Möglichkeit besteht darin, den Pfad ".." zu durchlaufen, zu speichern (durch Rekursion oder ein Array), bis ".." dieselbe Datei zurückgibt, die Sie gerade hatten (dh Sie befinden sich oben), und dann wieder zusammenzusetzen der Weg, wie Sie gehen. Ich habe gesehen, wie die Networker-Backup-Software von Legato dies während des Versuchs ausführte, um einen "wahren" Pfad zu erhalten (aber vielleicht nicht absolut). Aber es wäre viel mehr Code als der obige.
Ericlaw
Ich bin nicht sicher, warum jemand den Code geändert hat, um $ 1 anstelle von $ 0 zu verwenden. Ist $ 1 nicht das erste Argument für das Bash-Skript? Ich wollte den Pfad zum ausführenden Bash-Skript, nicht das erste Argument.
Ericlaw
27
#!/usr/bin/env bash
scriptDir="$(cd "$(dirname "$0")" && pwd -P)"
jhclark
quelle
Funktioniert auch unter MacOSX.
Alexar
1
Das ist super! Es gibt viele andere überkomplizierte Antworten.
Jason S
3
Dies funktioniert nur für Dateien in einem verknüpften Verzeichnis, nicht für verknüpfte Dateien im Allgemeinen
Gerhard Burger
1
Es ist auch hilfreich, unset -v CDPATHvor der CD zu schreiben, da CD unerwünschte Ausgaben verursachen kann, wenn CDPATH eingestellt ist.
Binary Phile
Um mindestens eine einzelne Ebene der Verknüpfung der Datei zu behandeln, können Sie auch auf kompatible Weise mit readlink testen (Macs haben kein -f): scriptDir=$(unset -v CDPATH; cd "$(dirname "$(readlink "$BASH_SOURCE" || echo "$BASH_SOURCE)")" && pwd -P)
Binary Phile
0

Dies verarbeitet Kombinationen von Symlinks und funktioniert für Dateien und Ordner:

#!/usr/bin/env bash
realpath()
{
    if ! pushd $1 &> /dev/null; then 
        pushd ${1##*/} &> /dev/null
        echo $( pwd -P )/${1%/*}
    else
        pwd -P
    fi
    popd > /dev/null
}

Aber es unterstützt nicht realpath's --relative-to. Dies würde die hier beschriebene Konvertierung erfordern .

Oliver
quelle
0

Ein anderer Ansatz:

# Install.
brew install coreutils

# Use the GNU variant.
grealpath --help
FMc
quelle