Czy istnieje sposób, aby skrypt powłoki pozyskał ścieżkę do siebie? Zajmuje mnie głównie bash, chociaż mam kilku współpracowników, którzy używają tcsh.
Zgaduję, że nie mam tu dużo szczęścia, ponieważ zaopatrzenie powoduje, że polecenia są wykonywane w bieżącej powłoce, podobnie $0
jak wywoływanie bieżącej powłoki, a nie skrypt źródłowy. Moja najlepsza myśl obecnie to zrobić source $script $script
, aby pierwszy parametr pozycyjny zawierał niezbędne informacje. Czy ktoś ma lepszy sposób?
Dla jasności pozyskuję skrypt, a nie uruchamiam go:
source foo.bash
Odpowiedzi:
W
tcsh
,$_
na początku skryptu będzie zawierać lokalizację, jeśli plik został pobrany, i$0
zawiera, jeśli został uruchomiony.W Bash:
źródło
> tcsh --version\n tcsh 6.14.00 (Astron) 2005-03-25 (i486-intel-linux) options wide,nls,dl,al,kan,rh,nd,color,filec
. Jeśli chodzi o pozyskiwanie go w sposób nieinteraktywny, plik źródłowy jest dołączany do pliku nadrzędnego, tak jakby rzeczywiście był jego częścią (tak, jak można to odróżnić), jak wspomniałeś w swoim pierwotnym pytaniu. Myślę, że obejście parametru pozycyjnego jest prawdopodobnie najlepszym podejściem. Jednak typowe pytanie brzmi: „dlaczego chcesz to zrobić”, a odpowiedź zazwyczaj brzmi: „nie rób tego - zrób to zamiast tego ” tam, gdzie „to” jest często przechowywane ....
isource
pracowały identycznie w tym zakresie. Zauważ, że$_
należy uzyskać do niego dostęp w pierwszej instrukcji w pliku, w przeciwnym razie będzie on zawierał ostatni argument poprzedniej komendy. Lubię dołączać shebang dla własnego odniesienia, więc wiem, dla jakiej powłoki powinien być i dla edytora, więc używa podświetlania składni.source
, a potem robiłem.
. Przepraszam za niekompetencję. Są rzeczywiście identyczne. W każdym razie$BASH_SOURCE
działa.Myślę, że możesz użyć
$BASH_SOURCE
zmiennej. Zwraca ścieżkę, która została wykonana:W następnym kroku powinniśmy sprawdzić, czy ścieżka jest względna, czy nie. Jeśli nie jest względny, wszystko jest w porządku. Jeśli tak, możemy sprawdzić ścieżkę za pomocą
pwd
, połączyć z/
i$BASH_SOURCE
.źródło
source
szuka,$PATH
jeśli podana nazwa nie zawiera/
. Kolejność wyszukiwania zależy od opcji powłoki, szczegółowe informacje można znaleźć w instrukcji obsługi.mydir="$(cd "$(dirname "$BASH_SOURCE")"; pwd)"
by działało?To rozwiązanie dotyczy tylko bash, a nie tcsh. Zauważ, że najczęściej podawana odpowiedź
${BASH_SOURCE[0]}
nie zadziała, jeśli spróbujesz znaleźć ścieżkę z funkcji.Przekonałem się, że ta linia zawsze działa, niezależnie od tego, czy plik jest pobierany czy uruchamiany jako skrypt.
Jeśli chcesz podążać za dowiązaniami symbolicznymi, użyj
readlink
ścieżki powyżej, rekursywnie lub nierekurencyjnie.Oto skrypt do wypróbowania i porównania z innymi proponowanymi rozwiązaniami. Wywołaj jako
source test1/test2/test_script.sh
lubbash test1/test2/test_script.sh
.Powód, dla którego działa jednolinijka, jest wyjaśniony przez użycie
BASH_SOURCE
zmiennej środowiskowej i jej powiązaniaFUNCNAME
.[Źródło: instrukcja Bash]
źródło
Dla dokładności i ze względu na wyszukiwarki, oto co oni robią ... Jest to wiki społeczności, więc możesz dodać inne odpowiedniki powłoki (oczywiście $ BASH_SOURCE będzie inny).
test.sh:
test2.sh:
Grzmotnąć:
Dziarskość
Zsh
źródło
called=$_; echo $called; echo $_
? Czy nie jest to druk$_
dwa razy?$_
parametru specjalnego: „Podczas uruchamiania powłoki ustaw bezwzględną nazwę ścieżki używaną do wywoływania powłoki lub skryptu powłoki wykonywanej jako przekazanej w środowisku lub liście argumentów. Następnie rozwija się do ostatniego argument do poprzedniego polecenia, po rozwinięciu. Ustaw także na pełną ścieżkę używaną do wywoływania każdego polecenia wykonanego i umieszczonego w środowisku wyeksportowanym do tego polecenia. Podczas sprawdzania poczty parametr ten przechowuje nazwę pliku poczty. ”#! /bin/sh
źródłowy ma nagłówek, co czyni go bezużytecznym do źródła. Rozpocznie to nową instancję/bin/sh
, ustawi zmienne, a następnie opuści tę instancję, pozostawiając instancję wywołującą niezmienioną.#
skryptu powłoki, jest komentarzem.#!
(shebang) ma swoje specjalne znaczenie tylko jako pierwszy wiersz wykonywanego skryptu . Jako pierwszy wiersz pozyskiwanego pliku jest to tylko komentarz.Działa to dla mnie w bash, dash, ksh i zsh:
Dane wyjściowe dla tych powłok:
Próbowałem sprawić, by działał dla csh / tcsh, ale jest to zbyt trudne; Pozostaję przy POSIX.
źródło
Byłem trochę zdezorientowany odpowiedzią wiki społeczności (od Shawna J. Goffa), więc napisałem skrypt, aby to rozwiązać. O
$_
znalazłem to: Wykorzystanie_
jako zmiennej środowiskowej przekazanej do polecenia . Jest to zmienna środowiskowa, więc łatwo jest niepoprawnie przetestować jej wartość.Poniżej znajduje się skrypt, a następnie jego wynik. Oni również są w tej istocie .
test-shell-default-variables.sh
Wyjście z
./test-shell-default-variables.sh {da,ba,z,k}sh
Czego się nauczyliśmy?
$BASH_SOURCE
$BASH_SOURCE
działa w trybie bash i tylko w bash.$0
polega na tym, że bieżący plik pochodzi z innego pliku. W takim przypadku$BASH_PROFILE
zawiera nazwę pliku źródłowego, a nie pliku źródłowego.$0
$0
ma taką samą wartość jak$BASH_SOURCE
w bash.$_
$_
pozostaje nietknięty przez myślnik i ksh.$_
rozpada się do ostatniego argumentu ostatniego wywołania.$_
na „bash”.$_
nietknięte. (podczas pozyskiwania jest to wynik reguły „ostatniego argumentu”).Symlinks
ksh
sh
sh
, w odniesieniu do tych testów zachowuje się jak myślnik.źródło
W przypadku powłoki bash uważam, że odpowiedź @Dennis Williamson jest najbardziej pomocna, ale nie zadziałała w przypadku
sudo
. To robi:źródło
Aby skrypt był zgodny zarówno z bash, jak i zsh, zamiast używać instrukcji if, wystarczy napisać
${BASH_SOURCE[0]:-${(%):-%x}}
. Wynikowa wartość zostanie pobrana,BASH_SOURCE[0]
gdy zostanie zdefiniowana, a${(%):-%x}}
gdy BASH_SOURCE [0] nie zostanie zdefiniowany.źródło
tl; dr
script=$(readlink -e -- "${BASH_SOURCE}")
(oczywiściedla bash )$BASH_SOURCE
przypadki testowepodany plik
/tmp/source1.sh
source
plik na różne sposobysource
od/tmp
source
od/
source
z różnych ścieżek względnych/tmp/a
i/var
Jeżeli chodzi o
$0
we wszystkich przypadkach, jeśli skrypt ma dodane polecenie
wtedy
source
skrypt jest zawsze drukowanyjednak jeśli skrypt został uruchomiony , np
to
$0
byłaby wartość ciągu/tmp/source1.sh
.źródło
ta odpowiedź opisuje, jak
lsof
i odrobina magii grep jest jedyną rzeczą, która wydaje się mieć szansę pracy dla zagnieżdżonych plików źródłowych w tcsh:źródło
Być może nie będzie to działać z dowiązaniami symbolicznymi lub źródłowymi, ale będzie działać z normalnymi plikami. Odniesiono jako odniesienie. @kenorb Brak nazwy katalogu, readlink, BASH_SOURCE.
źródło
$0
które zawiera informacje o aktualnie uruchomionym skrypcie, a nie źródłowym.W rzeczywistości „dirname $ 0” poprowadzi cię do skryptu, ale musisz go trochę zinterpretować:
Musisz przygotować się do obsługi „”. jako nazwa katalogu w niektórych typowych okolicznościach. Poeksperymentowałem trochę, ponieważ pamiętam nazwę dirname wbudowaną w ksh, która robi coś nieco inaczej, gdy „.” pojawia się w ścieżce.
źródło
$0
po prostu zawiera „bash” dla interaktywnej powłoki, i to wszystko, co widzi skrypt.