Jaki jest przenośny sposób dla skryptu (zsh) na określenie jego bezwzględnej ścieżki?
W systemie Linux używam czegoś takiego
mypath=$(readlink -f $0)
... ale to nie jest przenośne. (Np. readlink
Na Darwinie nie rozpoznaje -f
flagi, ani nie ma żadnego odpowiednika.) (Ponadto, użycie readlink
do tego jest, co prawda, dość niejasno wyglądającym włamaniem.)
Jaki jest bardziej przenośny sposób?
Odpowiedzi:
Dzięki
zsh
, to po prostu:Teraz jednak dla innych powłok są
realpath()
ireadlink()
są funkcjami standardowymi (te ostatnie są wywołaniem systemowym)realpath
ireadlink
nie są standardowymi poleceniami, chociaż niektóre systemy mają jedno lub drugie lub oba z różnymi zachowaniami i zestawem funkcji.Jak często, w celu przenoszenia, możesz skorzystać z
perl
:To działałoby bardziej jak GNU
readlink -f
niżrealpath()
(GNUreadlink -e
), ponieważ nie będzie narzekać, jeśli plik nie istnieje tak długo, jak jego nazwa katalogu.źródło
.zshrc
: Zobacz zamiast tego post .W Zsh możesz wykonać następujące czynności:
Lub, aby uzyskać katalog, w którym znajduje się skrypt:
Źródło: strona podręcznika zshexpn (1), sekcja ROZSZERZENIE HISTORII, podsekcja Modyfikatory (lub po prostu
info -f zsh -n Modifiers
).źródło
readlink -f
Raczej odpowiada to GNU$0:A
.Używam tego od kilku lat:
źródło
readlink -f
gdy sam skrypt jest dowiązaniem symbolicznym.zsh
, jeśli wykonam to bezpośrednio lub w podpowłoce (jak sugerowano) podczas pracy w moim domowym katalogu (/home/ville
), zostanie wydrukowane/home/ville/zsh
.Ta składnia powinna być przenośny do dowolnego stylu Bourne shell tłumacza (testowane z
bash
,ksh88
,ksh93
,zsh
,mksh
,dash
ibusybox sh
):Ta wersja dodaje zgodność ze starszą powłoką AT&T Bourne (bez POSIX):
źródło
$PWD
może być przesadą - możesz po prostu ustawić na prąd absolutny jakcd -P .
. Wątpię, czy zadziałałoby to w stylu bursztynu - ale powinno działać we wszystkich testowanych dla pierwszego. i tak robi dla mnie.zsh
adirname
jednak szybko wycofać hir / jej komentarz ...Zakładając, że naprawdę masz na myśli ścieżkę bezwzględną, tj. Ścieżkę z katalogu głównego:
Nawiasem mówiąc, działa to w dowolnej powłoce w stylu Bourne'a.
Jeśli miałeś na myśli ścieżkę z rozwiązanymi wszystkimi dowiązaniami symbolicznymi, to inna sprawa.
readlink -f
działa na Linuksie (z wyłączeniem niektórych zredukowanych systemów BusyBox), FreeBSD, NetBSD, OpenBSD i Cygwin, ale nie na OS / X, AIX, HP / UX lub Solaris. Jeśli takreadlink
, możesz wywołać go w pętli:Jeśli nie masz
readlink
, możesz to przybliżyćls -n
, ale działa to tylko wtedy, gdyls
nie zmienia w nazwie pliku żadnego niedrukowalnego znaku.(Dodatkowa
z
jest w przypadku, gdy cel łącza kończy się na nowej linii, która w przeciwnym razie pochłonęłaby komendę. Nawiasemrealpath
mówiąc, funkcja nie obsługuje tej nazwy nazw katalogów).źródło
ls
implementacje, które zniekształcają znaki niedrukowalne, gdy dane wyjściowe nie trafiają do terminala.touch Stéphane; LC_ALL=C busybox ls Stéphane | cat
→St??phane
(jeśli nazwa ma UTF-8, latin1 daje ci singla?
). Myślę, że widziałem to również w starszych komercyjnych Unices.busybox
jest? według gitbusybox ls
nie zmienił kodu od 2011 roku. Mójbusybox ls
- około 2013 roku - tego nie robi. To jeden - około 2012 - robi . To może wyjaśniać dlaczego. Czy masz już wbudowanąbusybox
obsługę Unicode - aby włączyć obsługę wchar? Możesz spróbować, w przeciwnym razie sprawdź opcje kompilacji wmkinitcpio
busybox
pakiecie.Pod warunkiem, że masz uprawnienia do wykonywania w bieżącym katalogu - lub w katalogu, z którego wykonałeś skrypt powłoki - jeśli potrzebujesz bezwzględnej ścieżki do katalogu, wszystko czego potrzebujesz
cd
.Krok 10
cd
specyfikacjiI dalej
pwd -P
Jest tak, ponieważ
cd -P
musi ustawić bieżący katalog roboczy na to, co wpwd -P
przeciwnym razie powinno zostać wydrukowane, i tocd -
musi wydrukować to$OLDPWD
, co działa:WYDAJNOŚĆ
czekaj na to...
WYDAJNOŚĆ
A kiedy
cd -
drukuję, drukuję$OLDPWD
.cd
ustawia się,$PWD
jak tylko jestemcd -P .
$PWD
teraz absolutną ścieżką do/
- więc nie potrzebuję żadnych innych zmiennych. I właściwie nie powinienem nawet potrzebować końcowego,.
ale jest określone zachowanie resetowania$PWD
do$HOME
w interaktywnej powłoce, gdy niecd
jest ozdobione. Więc to dobry nawyk, aby się rozwijać.Tak więc wykonanie powyższej czynności na ścieżce
${0%/*}
powinno być więcej niż wystarczające do zweryfikowania$0
ścieżki, ale w przypadku, gdy$0
jest to miękkie łącze, prawdopodobnie nie możesz zmienić katalogu na to, niestety.Oto funkcja, która sobie z tym poradzi:
Stara się zrobić tyle, ile może w bieżącej powłoce - bez wywoływania podpowłoki - chociaż są wywoływane podpowłoki z powodu błędów i miękkich linków, które nie wskazują na katalogi. To zależy od powłoki kompatybilnej z POSIX i kompatybilnej z POSIX,
ls
a także z czystej_function()
przestrzeni nazw. Nadal będzie działał dobrze bez tego drugiego, choć może wtedy nadpisaćunset
w takim przypadku niektóre bieżące funkcje powłoki. Zasadniczo wszystkie te zależności powinny być dość niezawodnie dostępne na maszynie uniksowej.Wywoływany z argumentami lub bez, pierwszą rzeczą, którą robi, jest resetowany
$PWD
do wartości kanonicznej - w razie potrzeby rozwiązuje wszelkie zawarte w nim linki do ich celów. Nazywany bez argumentów i to wszystko; ale wywoływany wraz z nimi, rozwiąże i kanonizuje ścieżkę dla każdego z nich lub wydrukuje wiadomośćstderr
dlaczego nie.Ponieważ działa on głównie w bieżącej powłoce, powinien być w stanie obsłużyć listę argumentów dowolnej długości. Wyszukuje również
$_zdlm
zmienną (która równieżunset
przechodzi, gdy jest już w toku ) i wypisuje swoją wartość C-esc natychmiast po prawej stronie każdego argumentu, po którym zawsze następuje pojedynczy\n
znak ewline.Często zmienia katalog, ale poza ustawieniem jego wartości kanonicznej, nie ma to wpływu
$PWD
, chociaż$OLDPWD
nie można w żaden sposób liczyć na to, kiedy się skończy.Próbuje jak najszybciej zrezygnować z każdego z argumentów. Najpierw próbuje
cd
się$1
. Jeśli to możliwe, wypisuje kanoniczną ścieżkę argumentu dostdout
. Jeśli nie może, sprawdza, czy$1
istnieje i nie jest linkiem miękkim. Jeśli to prawda, drukuje się.W ten sposób obsługuje dowolny argument typu pliku, do którego powłoka ma uprawnienia do adresowania, chyba że
$1
jest dowiązaniem symbolicznym, który nie wskazuje na katalog. W takim przypadku wywołujewhile
pętlę w podpowłoce.Wzywa
ls
do odczytania linku. Bieżący katalog musi zostać najpierw zmieniony na wartość początkową, aby niezawodnie obsługiwać ścieżki referencyjne, a zatem w podpowłoce podstawiania poleceń funkcja:Usuwa z lewej strony danych
ls
wyjściowych tak mało, jak to konieczne, aby w pełni zawierać nazwę łącza i ciąg znaków->
. Podczas gdy na początku starał się unikać zrobić zshift
i$IFS
okazuje się, że jest to najbardziej wiarygodna metoda tak blisko, jak mogę dowiedzieć. To jest to samo, co robi biedny link_mans_read Gillesa - i jest dobrze zrobione.Powtórzy ten proces w pętli, dopóki zwracana nazwa pliku
ls
nie będzie z pewnością miękkim linkiem. W tym momencie kanonizuje tę ścieżkę jak poprzednio, acd
następnie drukuje.Przykładowe użycie:
WYDAJNOŚĆ
A może…
WYDAJNOŚĆ
źródło
co z sympatycznym jednowierszowym, gdy dostępny jest python, aby zapobiec przedefiniowaniu algorytmu?
taki sam jak https://stackoverflow.com/a/7305217
źródło