Biorąc pod uwagę ścieżkę bezwzględną lub względną (w systemie uniksopodobnym), chciałbym ustalić pełną ścieżkę celu po rozwiązaniu jakichkolwiek pośrednich dowiązań symbolicznych. Punkty bonusowe za równoczesne rozwiązanie ~ notacji nazwy użytkownika.
Jeśli celem jest katalog, może być możliwe chdir () do katalogu, a następnie wywołanie getcwd (), ale naprawdę chcę to zrobić ze skryptu powłoki zamiast pisać pomocnika C. Niestety, powłoki mają tendencję do ukrywania przed użytkownikami istnienia dowiązań symbolicznych (jest to bash na OS X):
$ ls -ld foo bar
drwxr-xr-x 2 greg greg 68 Aug 11 22:36 bar
lrwxr-xr-x 1 greg greg 3 Aug 11 22:36 foo -> bar
$ cd foo
$ pwd
/Users/greg/tmp/foo
$
To, czego chcę, to funkcja resolver () taka, że po uruchomieniu z katalogu tmp w powyższym przykładzie resolve („foo”) == "/ Users / greg / tmp / bar”.
cd
to zrobić, zanim zadzwoniszpwd -P
. Innymi słowy: nie pozwoli ci to na usunięcie (zobacz cel) dowiązań symbolicznych do plików lub zepsutych dowiązań symbolicznych, a dla rozwiązania dowiązań symbolicznych istniejących katalogów musisz wykonać dodatkową pracę (przywrócić poprzedni działający katalog lub zlokalizować wywołaniacd
ipwd -P
w podpowłoce).Uwaga edytora: Powyższe działa z GNU
readlink
i FreeBSD / PC-BSD / OpenBSDreadlink
, ale nie w OS X od 10.11.GNU
readlink
oferuje dodatkowe, powiązane opcje, takie jak-m
rozstrzyganie dowiązania symbolicznego, czy istnieje ostateczny cel.Uwaga: od czasu wydania GNU coreutils 8.15 (2012-01-06) dostępny jest program realpath , który jest mniej tępy i bardziej elastyczny niż powyższe. Jest także kompatybilny z FreeBSD o tej samej nazwie. Zawiera także funkcję generowania ścieżki względnej między dwoma plikami.
[Dodatek administratora poniżej z komentarza halloleo - danorton]
W systemie Mac OS X (przez co najmniej 10.11.x) używaj
readlink
bez-f
opcji:Uwaga edytora: To nie rozwiąże rekurencyjnie dowiązań symbolicznych, a zatem nie zgłosi ostatecznego celu; np. biorąc pod uwagę dowiązanie symboliczne,
a
które wskazujeb
, co z kolei wskazujec
, będzie to tylko raportowaćb
(i nie zapewni, że zostanie wyprowadzone jako ścieżka bezwzględna ).Użyj następującego
perl
polecenia w systemie OS X, aby wypełnić lukę brakującejreadlink -f
funkcji:perl -MCwd -le 'print Cwd::abs_path(shift)' "$path"
źródło
readlink
działa na OSX, ale potrzebuje innej składni:readlink $path
bez-f
.Wydaje się, że „pwd -P” działa, jeśli chcesz tylko katalog, ale jeśli z jakiegoś powodu chcesz nazwę rzeczywistego pliku wykonywalnego, nie sądzę, żeby to pomogło. Oto moje rozwiązanie:
źródło
Jednym z moich ulubionych jest
realpath foo
źródło
realpath
Centos 6 z GNU coreutils 8.4.31. Natknąłem kilku innych na Unix i Linux , które mają Coreutils GNU pakowane bezrealpath
. Wydaje się więc, że zależy to nie tylko od wersji.realpath
więcej,readlink
ponieważ oferuje flagi opcji, takie jak--relative-to
wydaje się być dokładnie tym, o co prosisz - akceptuje ścieżkę arbitrażową, rozwiązuje wszystkie dowiązania symboliczne i zwraca „prawdziwą” ścieżkę - i jest to „standardowy * nix”, który prawdopodobnie wszystkie systemy już mają
źródło
Inny sposób:
źródło
Łącząc niektóre z wymienionych rozwiązań, wiedząc, że readlink jest dostępny w większości systemów, ale potrzebuje różnych argumentów, działa to dobrze dla mnie na OSX i Debianie. Nie jestem pewien co do systemów BSD. Być może warunkiem musi być
[[ $OSTYPE != darwin* ]]
wykluczenie-f
tylko z OSX.źródło
Oto, w jaki sposób można uzyskać rzeczywistą ścieżkę do pliku w systemie MacOS / Unix za pomocą wbudowanego skryptu Perl:
Podobnie, aby uzyskać katalog pliku dowiązania symbolicznego:
źródło
Czy ścieżka jest katalogiem, czy może plikiem? Jeśli jest to katalog, to proste:
Jeśli jednak może to być plik, to nie zadziała:
ponieważ dowiązanie symboliczne może przekształcić się w ścieżkę względną lub pełną.
W skryptach muszę znaleźć prawdziwą ścieżkę, aby móc odwoływać się do konfiguracji lub innych skryptów zainstalowanych razem z nią, używam tego:
Możesz ustawić
SOURCE
dowolną ścieżkę pliku. Zasadniczo, dopóki ścieżka jest dowiązaniem symbolicznym, rozwiązuje to dowiązanie symboliczne. Sztuczka znajduje się w ostatnim wierszu pętli. Jeśli rozstrzygnięte dowiązanie symboliczne jest bezwzględne, użyje go jakoSOURCE
. Jeśli jednak jest względny, przygotujeDIR
go, który został rozwiązany w prawdziwej lokalizacji za pomocą prostej sztuczki, którą opisałem po raz pierwszy.źródło
źródło
Uwaga: Uważam, że jest to solidne, przenośne, gotowe rozwiązanie, które z tego powodu jest niezmiennie długie .
Poniżej znajduje się w pełni zgodny ze standardem POSIX skrypt / funkcja, która jest zatem wieloplatformowa (działa również na macOS, którego
readlink
wciąż nie obsługuje-f
od 10.12 (Sierra)) - używa tylko funkcji języka powłoki POSIX i tylko wywołań narzędzi zgodnych z POSIX .Jest to przenośna implementacja GNU
readlink -e
(bardziej rygorystyczna wersjareadlink -f
).Można uruchomić skrypt z
sh
lub pozyskać funkcję wbash
,ksh
izsh
:Na przykład w skrypcie możesz użyć go w następujący sposób, aby uzyskać prawdziwy katalog pochodzenia skryptu uruchomionego, z rozwiązanymi dowiązaniami symbolicznymi:
rreadlink
definicja skryptu / funkcji:Kod został przyjęty z wdzięcznością z tej odpowiedzi .
Ja również stworzył
bash
opartych samodzielną wersję użytkową tutaj , które można zainstalować znpm install rreadlink -g
, jeśli masz zainstalowany node.js.Styczna w zakresie bezpieczeństwa:
jarno , w odniesieniu do funkcji zapewniającej, że wbudowana funkcja
command
nie jest zaciemniona przez alias lub funkcję powłoki o tej samej nazwie, pyta w komentarzu:Motywacją do
rreadlink
zapewnienia, żecommand
ma to swoje oryginalne znaczenie, jest obejście (łagodnych) wygodnych aliasów i funkcji często używanych do cieniowania standardowych poleceń w interaktywnych powłokach, takich jak redefiniowanie wls
celu włączenia ulubionych opcji.Myślę, że to na pewno powiedzieć, że jeśli masz do czynienia z niezaufanych, szkodliwego środowiska, martwić
unalias
albounset
- albo, jeśli o to chodzi,while
,do
, ... - jest nowo nie jest problemem.Jest coś , na czym funkcja musi polegać, aby mieć swoje pierwotne znaczenie i zachowanie - nie ma na to sposobu.
To, że powłoki podobne do POSIX pozwalają na ponowne zdefiniowanie wbudowanych narzędzi, a nawet słowa kluczowe w języku, jest z natury zagrożeniem bezpieczeństwa (a pisanie kodu paranoicznego jest ogólnie trudne).
Aby w szczególności odpowiedzieć na twoje wątpliwości:
Funkcja polega
unalias
iunset
ma swoje oryginalne znaczenie. Ponowne zdefiniowanie ich jako funkcji powłoki w sposób, który zmienia ich zachowanie, stanowiłoby problem; redefinicja jako alias niekoniecznie stanowi problem, ponieważ cytowanie (części) nazwy polecenia (np.\unalias
) pomija aliasy.Jednak cytowanie jest nie opcja dla powłoki słów kluczowych (
while
,for
,if
,do
, ...) i gdy powłoka słowa kluczowe biorą górę nad powłoki funkcji , wbash
izsh
aliasy mają najwyższy priorytet, tak aby zabezpieczyć się przed tulejką kluczowe redefiniowaniem należy uruchomićunalias
z ich nazwy (chociaż w nieinteraktywnychbash
powłokach (takich jak skrypty) aliasy nie są domyślnie rozwijane - tylko jeślishopt -s expand_aliases
zostaną jawnie wywołane jako pierwsze).Aby mieć pewność, że
unalias
- jako wbudowany - ma swoje oryginalne znaczenie, musisz\unset
go najpierw użyć , co wymaga, abyunset
miało to oryginalne znaczenie:unset
jest wbudowaną powłoką , więc aby upewnić się, że jest wywoływana jako taka, musisz upewnić się, że sama nie zostanie ponownie zdefiniowana jako funkcja . Chociaż możesz ominąć formularz aliasu z cytowaniem, nie możesz ominąć formularza funkcji powłoki - catch 22.Tak więc, o ile nie mogę polegać na
unset
swoim pierwotnym znaczeniu, z tego co mogę powiedzieć, nie ma gwarantowanego sposobu obrony przed wszystkimi złośliwymi przedefiniowaniami.źródło
[
jako aliasudash
abash
oraz jako powłoki w funkcjibash
.while
jako funkcję wbash
,ksh
izsh
(niedash
), ale tylko zefunction <name>
składnią:function while { echo foo; }
prace (while() { echo foo; }
nie). Nie będzie to jednak przesłaniaćwhile
słowa kluczowego , ponieważ słowa kluczowe mają wyższy priorytet niż funkcje (jedynym sposobem na wywołanie tej funkcji jest as\while
). Wbash
izsh
aliasy mają wyższy priorytet niż słowa kluczowe, więc alias redefinicji słów kluczowych je cienia (alebash
domyślnie tylko w interaktywnych powłokach, chyba żeshopt -s expand_aliases
jest to jawnie wywołane).Typowe skrypty powłoki często muszą znajdować katalog „domowy”, nawet jeśli są wywoływane jako dowiązanie symboliczne. Skrypt musi więc znaleźć swoją „prawdziwą” pozycję już od 0 USD.
w moim systemie wypisuje skrypt zawierający następujące elementy, które powinny być dobrą wskazówką, czego potrzebujesz.
źródło
Spróbuj tego:
źródło
Ponieważ przez lata napotykałem na to wiele razy i tym razem potrzebowałem przenośnej wersji czystej bash, której mogłem używać na OSX i Linuksie, napisałem:
Żywa wersja mieszka tutaj:
https://github.com/keen99/shell-functions/tree/master/resolve_path
ale ze względu na SO, oto aktualna wersja (czuję, że jest dobrze przetestowana .. ale jestem otwarty na opinie!)
Może nie będzie trudno sprawić, że będzie działać dla zwykłej powłoki bourne (sh), ale nie próbowałem ... Za bardzo lubię $ FUNCNAME. :)
oto klasyczny przykład, dzięki naparowi:
użyj tej funkcji, a zwróci ścieżkę -real-:
źródło
Aby obejść niezgodność komputera Mac, wpadłem na pomysł
Nie świetne, ale w różnych systemach operacyjnych
źródło
python -c "from os import path; print(path.realpath('${SYMLINK_PATH}'));"
prawdopodobnie miałby więcej sensu. Jednak do czasu, kiedy będziesz musiał używać Pythona ze skryptu powłoki, prawdopodobnie powinieneś po prostu użyć Pythona i zaoszczędzić sobie bólu głowy podczas wieloplatformowego skryptowania powłoki.dirname
,basename
, ireadlink
są zewnętrzne narzędzia , nie zapłacić Zabudowy;dirname
ibasename
są częścią POSIX,readlink
nie jest.php
pochodzi z OS X. Jednak nawet jeśli w treści pytania wspomniano OS X, nie jest on oznaczony jako taki i staje się jasny że ludzie na różnych platformach przychodzą tutaj, aby uzyskać odpowiedzi, dlatego warto wskazać, co jest specyficzne dla platformy / inne niż POSIX.To jest resolver symlink w Bash, który działa niezależnie od tego, czy dowiązanie jest katalogiem czy innym katalogiem:
Zauważ, że wszystkie
cd
iset
rzeczy odbywa się w podpowłoce.źródło
{}
Wokół()
nie są niepotrzebne, jeśli nie ma()
nazwy za nazwą funkcji. Bash akceptuje deklaracje funkcji bez,()
ponieważ powłoka nie ma list parametrów w deklaracjach i nie wykonuje wywołań,()
więc deklaracje funkcji()
nie mają większego sensu.Przedstawiam tutaj rozwiązanie, które moim zdaniem jest rozwiązaniem wieloplatformowym (przynajmniej Linux i macOS), które obecnie działa dla mnie dobrze.
Oto rozwiązanie macOS (tylko?). Być może lepiej pasuje do pierwotnego pytania.
źródło
Moja odpowiedź tutaj Bash: jak uzyskać prawdziwą ścieżkę dowiązania symbolicznego?
ale w skrócie bardzo przydatny w skryptach:
Są one częścią jąder GNU, odpowiednich do użycia w systemach Linux.
Aby wszystko przetestować, umieszczamy dowiązanie symboliczne w / home / test2 /, poprawiamy kilka dodatkowych rzeczy i uruchamiamy / wywołujemy go z katalogu głównego:
Gdzie
źródło
W przypadku, gdy nie można użyć pwd (np. Wywoływania skryptów z innej lokalizacji), użyj realpath (z lub bez nazwy katalogu):
Działa zarówno podczas wywoływania przez (wiele) dowiązań symbolicznych, jak i podczas bezpośredniego wywoływania skryptu - z dowolnej lokalizacji.
źródło