Uzyskaj ścieżkę bieżącego skryptu po uruchomieniu za pomocą dowiązania symbolicznego


58

Mam narzędzie składające się z kilku katalogów z niektórymi skryptami bash i plikami pomocniczymi, które zostaną wdrożone na kilku komputerach, ewentualnie w innym katalogu na każdym komputerze. Skrypty muszą mieć możliwość odwoływania się do ścieżek względem siebie, więc muszę mieć możliwość uzyskania ścieżki do aktualnie wykonywanego pliku.

Zdaję sobie sprawę z dirname $0idiomu, który działa idealnie, gdy mój skrypt jest wywoływany bezpośrednio. Niestety istnieje chęć stworzenia dowiązań symbolicznych do tych skryptów z zupełnie innego katalogu i nadal mieć względną logikę ścieżek.

Przykład ogólnej struktury suchej jest następujący:

/
 |-usr/local/lib
 |  |-foo
 |  |  |-bin
 |  |  |  |-script.sh
 |  |  |-res
 |  |  |  |-resource_file.txt
 |-home/mike/bin
 |  |-link_to_script (symlink to /usr/local/lib/foo/bin/script.sh)

Jak mogę w sposób wiarygodny odwoływać się /usr/local/lib/foo/res/resource_file.txtdo script.shtego, czy jest przywoływany przez /usr/local/lib/foo/bin/script.shczy ~mike/bin/link_to_script?

Odpowiedzi:


79

Wypróbuj to jako rozwiązanie ogólnego zastosowania:

DIR="$(cd "$(dirname "$0")" && pwd)"

W konkretnym przypadku następujących dowiązań symbolicznych możesz również to zrobić:

DIR="$(dirname "$(readlink -f "$0")")"

Działa idealnie i jest o wiele prostszy niż rzeczy, których próbowałem. Dzięki!
Mike Deck

@MikeDeck Enjoy. Zauważ, że naprawiłem niektóre problemy z cytowaniem od pierwszego opublikowania ... możesz skorzystać z opcji z najnowszej edycji w przypadku, gdy masz na swojej drodze spacje lub inne zwariowane postacie. Nawet jeśli nie ma to znaczenia dla tego projektu, możesz skopiować kod ze swoich własnych skryptów, a wybór najlepszej opcji jest wtedy ważny!
Caleb

1
Powinienem wyjaśnić, drugi działa doskonale. Pierwsze podane rozwiązanie nie działa w przypadku dowiązań symbolicznych w moim systemie.
Mike Deck

4
@MikeDeck: Pierwsze rozwiązanie działa w typowym przypadku, gdy różne katalogi są połączone symbolicznie jako część ścieżki, ale nie pomoże, jeśli końcowy plik binarny jest dowiązaniem symbolicznym. Tym zajmuje się drugi.
Caleb

1
Nie działa, jeśli plik skryptu to sourced (np. $ source ./sript.sh) Działa to w obu przypadkach:DIR="$(cd "$(dirname "$BASH_SOURCE")" && pwd)"
FractalSpace

7

jedna linia:

cd $(dirname $([ -L $0 ] && readlink -f $0 || echo $0))

2
Odpowiedzi w jednym wierszu zazwyczaj nie są najbardziej pomocne. Rozważ poszerzenie swojej odpowiedzi o wyjaśnienia, linki lub dokumentację, które dodatkowo wspierają proponowane rozwiązanie.
HalosGhost

1
właściwie nie musisz tego robić, wersja readlink oryginalnej odpowiedzi działa dobrze, jeśli w ogóle nie ma w niej dowiązania symbolicznego
THESorcerer


0

Jeden mały dodatek do powyższego skryptu. Opcja -P do pwd podąża za dowiązaniami symbolicznymi

DIR="$(cd "$(dirname "$0")" && pwd -P)"

7
Działa to tylko wtedy, gdy dowiązanie symboliczne jest częścią struktury katalogów. Nie działa, gdy sam plik jest połączony.
Oliver Gondža
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.