Jak mogę odzyskać bezwzględną nazwę pliku w skrypcie powłoki w Mac OS X?

19

Chciałbym odzyskać bezwzględną nazwę pliku skryptu, który jest aktualnie wykonywany. Linki również powinny zostać rozwiązane.

W systemie Linux wygląda to tak:

$(readlink -mn "$0")

ale readlinkwydaje się działać zupełnie inaczej w Mac OS X.

Przeczytałem, że odbywa się to za pomocą

$(realpath $0)

w BSD, ale to też nie działa. Mac OS X nie ma realpath.

Dowolny pomysł?

Huxi
źródło
1
Zobacz to pytanie na SO: stackoverflow.com/questions/799679/…
Telemachus
Jeszcze więcej opcji: stackoverflow.com/questions/7665/…
Gerhard Burger

Odpowiedzi:

19

Oszukuję i używam perla do tego właśnie:

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

Można by pomyśleć, że po prostu napiszę cały skrypt w perlu, i często to robię, ale nie zawsze.

ericslaw
źródło
To działa, wielkie dzięki. Jak najszybciej dam ci głos. Czy ktoś ma na to sposób „czystej powłoki”?
Huxi,
1
Obawiam się, że to jest tak dobre, jak to możliwe. (Biorąc pod uwagę wiele wieloliniowych włamań do „czystej powłoki”, które można znaleźć w Google.)
Arjan,
inną możliwością (choć brzydką) jest przejście przez ścieżkę „..”, zapamiętywanie (przez rekurencję lub tablicę), aż „..” zwróci ten sam plik, który właśnie miałeś (tj. jesteś na górze), a następnie wrócisz ścieżka jak idziesz. Widziałem oprogramowanie do tworzenia kopii zapasowych Legato Networker, które robi to podczas strace, jako metodę uzyskania „prawdziwej” ścieżki (ale być może nie absolutnej). Ale byłoby to o wiele więcej kodu niż powyższe.
ericslaw
Nie jestem pewien, dlaczego ktoś zmodyfikował kod, aby używał 1 $ zamiast 0 $. Czy 1 $ nie jest pierwszym argumentem skryptu bash? Chciałem ścieżki do wykonującego skryptu bash, nie jest to pierwszy argument.
ericslaw
27
#!/usr/bin/env bash
scriptDir="$(cd "$(dirname "$0")" && pwd -P)"
jhclark
źródło
Działa również w MacOSX.
Alexar
1
To jest super! Istnieje wiele innych zbyt skomplikowanych odpowiedzi.
Jason S
3
Działa to tylko dla plików w katalogu dowiązań symbolicznych, a nie ogólnie dla plików dowiązań symbolicznych
Gerhard Burger
1
Pomocne jest także unset -v CDPATHwcześniejsze przejście do cd, ponieważ cd może powodować niechciane wyjście, jeśli ustawiony jest CDPATH.
Binarny Phile
Do czynienia z co najmniej jednej warstwy symlinking pliku, można również testy w kompatybilnym sposób z readlink (macs nie ma -f): scriptDir=$(unset -v CDPATH; cd "$(dirname "$(readlink "$BASH_SOURCE" || echo "$BASH_SOURCE)")" && pwd -P)
Binary phile
0

To obsługuje kombinacje dowiązań symbolicznych i działa na plikach i folderach:

#!/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
}

Ale nie obsługuje realpath - w odniesieniu do. Wymagałoby to opisanej tutaj konwersji .

Oliver
źródło
0

Inne podejście:

# Install.
brew install coreutils

# Use the GNU variant.
grealpath --help
FMc
źródło