Odwołanie się do pliku względem wykonywanego skryptu

97

W pisanym przeze mnie skrypcie bash używam sourcedo dołączania zmiennej zdefiniowanej w pliku konfiguracyjnym. Skrypt do wykonania to act.sh, a skrypt do wykonania sourced to act.conf.sh, więc act.shmam:

source act.conf.sh

Jednak działa to tylko wtedy, gdy działa act.shw katalogu zawierającym go, ponieważ act.conf.shodnosi się do pliku umieszczonego w katalogu roboczym. Czy istnieje rozwiązanie, które sprawi, że będzie odnosił się do pliku względem wykonywanego skryptu bez wywoływania cd? Dzięki.

Ryan Li
źródło

Odpowiedzi:

121

Zobacz: BASH FAQ wpis nr 28: „Jak określić lokalizację mojego skryptu? Chcę czytać niektóre pliki konfiguracyjne z tego samego miejsca”.

Żadne rozwiązanie nie będzie działać w 100% przypadków:

Należy zdać sobie sprawę, że w ogólnym przypadku ten problem nie ma rozwiązania. Każde podejście, o którym być może słyszałeś, i każde podejście, które zostanie szczegółowo opisane poniżej, ma wady i będzie działać tylko w określonych przypadkach. Przede wszystkim staraj się całkowicie uniknąć problemu, nie polegając na lokalizacji skryptu!

Jeśli musisz napisać bardzo wielokrotnego użytku, narzędzia, a następnie biorąc poprawną ścieżkę jako parametr do skryptu będzie najbardziej wiarygodna metoda .

Zakładając, że twój skrypt będzie uruchamiany tylko z pewnych powłok i tylko przy wymaganej odrobinie elastyczności, prawdopodobnie możesz złagodzić tę paranoję. Nadal dobrze jest spojrzeć na swoje opcje. Istnieją wspólne wzorce, których ludzie używają, a które są szczególnie problematyczne.

W szczególności FAQ zaleca unikanie bardzo często używanej $0zmiennej:

Nic, co czyta $0, nigdy nie będzie kuloodporne, ponieważ $0samo w sobie jest zawodne.

Zamiast tego możesz użyć $BASH_SOURCE. Coś takiego:

source "${BASH_SOURCE%/*}/act.conf.sh"

Rozwiązanie to ma też pewne zastrzeżenia. Zajrzyj na stronę z często zadawanymi pytaniami, aby zobaczyć kompromisy między różnymi rozwiązaniami. Wydaje się, że zalecają cdw połączeniu z $BASH_SOURCEw przypadkach, w których będzie to działać dla Ciebie, ponieważ pojawia się przydatny błąd, gdy nie rozwija się prawidłowo.

Ignacio Vazquez-Abrams
źródło
1
Dzięki, skorzystałbym readlink. Nie byłem w stanie określić słów kluczowych do wyszukania, więc opublikowałem tutaj pytanie ...
Ryan Li
9
Czy możesz dodać odpowiednie informacje do odpowiedzi na wypadek, gdyby zdarzyło się, że bash FAQ nie działa?
Merlyn Morgan-Graham
3
Link zaleca :,cd "${BASH_SOURCE%/*}" || exit lub read somevar < "${BASH_SOURCE%/*}/etc/somefile", Link zdecydowanie odradza $0 „Nic, co brzmi 0 USD, nigdy nie będzie kuloodporne, ponieważ samo 0 USD jest zawodne”.
ThorSummoner,
10
Co robi% / * po BASH_SOURCE i jak?
Silicomancer
34

Zobacz to: Bash: Jak _najlepiej_ dołączyć inne skrypty?

Proponuję użyć:

source $(dirname $0)/act.conf.sh
vagovszkym
źródło
8
To nie jest odpowiedź, której szukasz. $0jest z natury wadliwy. Zobacz najczęściej głosowaną i zaakceptowaną odpowiedź, aby dowiedzieć się, dlaczego lub po prostu przeczytaj mywiki.wooledge.org/BashFAQ/028 - krótkie obejście zadanego pytania jest takie jaksource "${BASH_SOURCE%/*}/act.conf.sh"
Merlyn Morgan-Graham
5

Spróbuj wykonać następujące czynności:

source ${BASH_SOURCE[0]/%act.sh/act.conf.sh}
bezradny
źródło
1

Zwykle dodaję to do moich skryptów.

cd $(dirname $BASH_SOURCE)

Następnie cały kolejny kod jest wykonywany względem ścieżki skryptu.

Gayan Weerakutti
źródło