realpathnie wydaje się być dostępny w systemie Mac (OS X 10.11 „El Capitan”). :-(
Laryx Decidua
realpathnie wydaje się być również dostępny w CentOS 6
user5359531
6
na osx, brew install coreutilsprzyniesierealpath
Kevin Chen
Na moim Ubuntu 18.04 realpathjest już obecny. Nie musiałem go instalować osobno.
Acumenus
Zaskakujące realpathjest , że jest dostępny na Git for Windows (przynajmniej dla mnie).
Andrew Keeton,
104
Jeśli masz zainstalowany pakiet coreutils, możesz ogólnie użyć go readlink -f relative_file_namew celu odzyskania absolutnego (z rozwiązanymi wszystkimi dowiązaniami symbolicznymi)
Zachowanie w tym przypadku różni się nieco od tego, o co prosi użytkownik, będzie również śledzić i rozwiązywać rekurencyjne dowiązania symboliczne w dowolnym miejscu ścieżki. W niektórych przypadkach możesz tego nie chcieć.
ffledgling
1
@BradPeabody Działa to na komputerze Mac, jeśli zainstalujesz coreutils z homebrew brew install coreutils. Jednak plik wykonywalny jest poprzedzony przez ag:greadlink -f relative_file_name
Miguel Isla
2
Zauważ, że strona podręcznika readlink (1) ma jako pierwsze zdanie opisu: „Uwaga realpath (1) jest poleceniem preferowanym do wykorzystania przy tworzeniu funkcji kanonicznych”.
josch
1
możesz użyć -e zamiast -f, aby sprawdzić, czy plik / katalog istnieje, czy nie
readlink jest prostym rozwiązaniem dla Linuksa, ale to rozwiązanie działa również na OSX, więc +1
thetoolman
1
Ten skrypt nie jest odpowiednikiem tego, co realpathlub readlink -fzrobić. Na przykład nie działa na ścieżkach, w których ostatni składnik jest dowiązaniem symbolicznym.
josch
2
@josch: Pytanie nie dotyczy rozwiązywania linków symbolicznych. Ale jeśli chcesz to zrobić, możesz podać -Popcję pwdpolecenia:echo "$(cd "$(dirname "$1")"; pwd -P)/$(basename "$1")"
Eugen Konkov
4
Podoba mi się odpowiedź, ale działa tylko wtedy, gdy użytkownik może przejść do katalogu. Nie zawsze jest to możliwe.
Matthias B
34
Głosowałem za wybraną odpowiedzią, ale chciałem podzielić się rozwiązaniem. Wadą jest to, że jest to tylko Linux - spędziłem około 5 minut próbując znaleźć odpowiednik OSX, zanim doszedłem do przepełnienia stosu. Jestem pewien, że tam jest.
W systemie Linux można używać readlink -ew połączeniu z dirname.
$(dirname $(readlink -e ../../../../etc/passwd))
plony
/etc/
A potem używasz dirnamesiostry ', basenameaby po prostu uzyskać nazwę pliku
Doskonała pozycja z dirname, readlink, i basename. To pomogło mi uzyskać absolutną ścieżkę dowiązania symbolicznego, a nie jego cel.
kevinarpe
Nie działa, gdy chcesz zwrócić ścieżkę do dowiązań symbolicznych (co akurat muszę zrobić ...).
Tomáš Zato - Przywróć Monikę
Jak mogłeś kiedykolwiek znaleźć absolutną ścieżkę do ścieżki, która nie istnieje?
synthesizerpatel
@synthesizerpatel Całkiem łatwo, pomyślałbym; jeśli wchodzę /home/GKFXi piszę touch newfile, to zanim naciśnę klawisz Enter, możesz dojść do wniosku, że mam na myśli „create / home / GKFX / newfile”, co jest bezwzględną ścieżką do pliku, który jeszcze nie istnieje.
GKFX
25
Myślę, że jest to najbardziej przenośny:
abspath(){
cd "$(dirname "$1")"
printf "%s/%s\n""$(pwd)""$(basename "$1")"
cd "$OLDPWD"}
Nie ma potrzeby ponownego odtwarzania płyty CD. Zobacz stackoverflow.com/a/21188136/1504556 . Twoja jest najlepszą odpowiedzią na tej stronie, IMHO. Dla zainteresowanych link daje wyjaśnienie, dlaczego to rozwiązanie działa.
peterh
To nie jest zbyt przenośne, dirnamejest podstawowym narzędziem GNU, nie jest wspólne dla wszystkich unixenów, jak sądzę.
O mój Boże, dziękuję. Próbuję naprawić wersję używaną ${1##*/}od jednego dnia, a teraz, kiedy zastąpiłem ten kosz basename "$1", wydaje się, że w końcu poprawnie obsługują ścieżki kończące się na /.
l3l_aze
NB, to nie działa dobrze ze ścieżką kończącą się na../..
Alex Coventry,
16
realpath jest prawdopodobnie najlepszy
Ale ...
Początkowe pytanie było bardzo zagmatwane na początku, z przykładem słabo powiązanym z zadanym pytaniem.
Wybrana odpowiedź w rzeczywistości odpowiada na podany przykład, a nie na pytanie w tytule. Pierwsza komenda to odpowiedź (czy naprawdę? Wątpię) i równie dobrze mogłaby działać bez znaku „/”. I nie widzę, co robi drugie polecenie.
Kilka problemów jest mieszanych:
zmiana względnej ścieżki na absolutną, cokolwiek by to oznaczało, prawdopodobnie nic. ( Zazwyczaj, jeśli wydasz takie polecenie, jak touch foo/barnazwa ścieżki, foo/barmusi istnieć dla Ciebie i prawdopodobnie zostać użyta w obliczeniach, zanim plik zostanie faktycznie utworzony ).
może istnieć kilka bezwzględnych nazw ścieżek, które oznaczają ten sam plik (lub potencjalny plik), w szczególności z powodu dowiązań symbolicznych (dowiązań symbolicznych) na ścieżce, ale prawdopodobnie z innych powodów (urządzenie może być zamontowane dwa razy jako tylko do odczytu). Można lub nie chcieć rozwiązywać jawności takich dowiązań symbolicznych.
dotarcie do końca łańcucha dowiązań symbolicznych do pliku lub nazwy niebędącej dowiązaniem symbolicznym. To może, ale nie musi, dać absolutną nazwę ścieżki, w zależności od tego, jak jest to zrobione. I można, ale nie trzeba, przekształcić to w absolutną ścieżkę.
Polecenie readlink foobez opcji daje odpowiedź tylko wtedy, gdy jego argumentfoo jest dowiązanie symboliczne, a ta odpowiedź jest wartością tego dowiązania symbolicznego. Żaden inny link nie jest używany. Odpowiedzią może być ścieżka względna: cokolwiek było wartością argumentu dowiązania symbolicznego.
Jednak, readlink ma opcje (-f -e lub -m), które będą działać dla wszystkich plików i podadzą jedną bezwzględną ścieżkę dostępu (tę bez dowiązań symbolicznych) do pliku faktycznie oznaczonego przez argument.
Działa to dobrze w przypadku wszystkiego, co nie jest dowiązaniem symbolicznym, chociaż można chcieć użyć bezwzględnej nazwy ścieżki bez rozwiązywania pośrednich dowiązań symbolicznych na ścieżce. Odbywa się to za pomocą poleceniarealpath -s foo
W przypadku argumentu dowiązania symbolicznego, readlinkz jego opcjami ponownie rozwiążemy wszystkie dowiązania symboliczne na bezwzględnej ścieżce do argumentu, ale będzie to również obejmować wszystkie dowiązania symboliczne, które można napotkać, podążając za wartością argumentu. Możesz tego nie chcieć, jeśli chcesz mieć bezwzględną ścieżkę do samego dowodu symbolicznego argumentu, a nie do tego, do czego może ono prowadzić. Ponownie, jeśli foojest dowiązaniem symbolicznym, realpath -s foootrzyma ścieżkę bezwzględną bez rozpoznawania dowiązań symbolicznych, w tym podanego jako argument.
Bez tej -sopcji realpathrobi to samo, co
readlinkpoza zwykłym odczytem wartości linku, a także kilkoma innymi rzeczami. Po prostu nie jest dla mnie jasne, dlaczego readlinkma swoje opcje, stwarzając pozornie niepożądaną nadmiarowość
realpath .
Eksploracja sieci nie mówi nic więcej, z wyjątkiem tego, że mogą występować pewne różnice między systemami.
Wniosek: realpathto najlepsza komenda do użycia, z największą elastycznością, przynajmniej do użycia tutaj wymaganego.
Moim ulubionym rozwiązaniem było to przez @EugenKonkov ponieważ nie sugerować obecność innych mediów (pakiet coreutils).
Ale zawiodło dla ścieżek względnych "." i „..”, więc tutaj jest nieco ulepszona wersja obsługująca te specjalne przypadki.
cdJednak nadal kończy się niepowodzeniem, jeśli użytkownik nie ma uprawnień do dostępu do katalogu nadrzędnego ścieżki względnej.
#! /bin/sh# Takes a path argument and returns it as an absolute path. # No-op if the path is already absolute.function to-abs-path {local target="$1"if["$target"=="."];then
echo "$(pwd)"elif["$target"==".."];then
echo "$(dirname "$(pwd)")"else
echo "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"fi}
Jeśli używasz bash w systemie Mac OS X, który ani nie ma realpath, ani jego readlink nie może wydrukować bezwzględnej ścieżki, możesz mieć wybór i musisz zakodować własną wersję, aby ją wydrukować. Oto moja realizacja:
(czysty bash)
abspath(){local thePath
if[[!"$1"=~^/]];then
thePath="$PWD/$1"else
thePath="$1"fi
echo "$thePath"|(
IFS=/
read -a parr
declare -a outp
for i in"${parr[@]}";docase"$i"in''|.)continue;;..)
len=${#outp[@]}if((len==0));thencontinueelse
unset outp[$((len-1))]fi;;*)
len=${#outp[@]}
outp[$len]="$i";;esacdone
echo /"${outp[*]}")}
(użyj gawk)
abspath_gawk(){if[[-n "$1"]];then
echo $1|gawk '{
if(substr($0,1,1) != "/"){
path = ENVIRON["PWD"]"/"$0
} else path = $0
split(path, a, "/")
n = asorti(a, b,"@ind_num_asc")
for(i in a){
if(a[i]=="" || a[i]=="."){
delete a[i]
}
}
n = asorti(a, b, "@ind_num_asc")
m = 0
while(m!=n){
m = n
for(i=1;i<=n;i++){
if(a[b[i]]==".."){
if(b[i-1] in a){
delete a[b[i-1]]
delete a[b[i]]
n = asorti(a, b, "@ind_num_asc")
break
} else exit 1
}
}
}
n = asorti(a, b, "@ind_num_asc")
if(n==0){
printf "/"
} else {
for(i=1;i<=n;i++){
printf "/"a[b[i]]
}
}
}'fi}
Dziękujemy za ten fragment kodu, który może zapewnić ograniczoną krótkoterminową pomoc. Właściwe wyjaśnienie znacznie poprawiłoby jego długoterminową wartość, pokazując, dlaczego jest to dobre rozwiązanie problemu, i uczyniłoby go bardziej użytecznym dla przyszłych czytelników z innymi, podobnymi pytaniami. Proszę edytować swoją odpowiedź dodać kilka wyjaśnień, w tym założeń już wykonanych.
Rozwiązanie to poprawnie rozwiązuje przypadek, w którym znajduje się ostatni element ścieżki .., w którym to przypadku odpowiedź "$(pwd)/$(basename "$1")"in @ ernest-a pojawi się jako accurate_sub_path/spurious_subdirectory/...
Na bash-4.3-p46 to nie działa: powłoka drukuje pustą linię, kiedy uruchamiamdir=`cd ".."` && echo $dir
Michael
0
Jest to rozwiązanie łańcuchowe od wszystkich innych, na przykład w przypadku realpathniepowodzenia, ponieważ nie jest zainstalowane lub kończy się z kodem błędu, wówczas podejmowane są próby rozwiązania następnego, dopóki nie uzyska właściwej ścieżki.
Nie mogłem znaleźć rozwiązania, które byłoby zgrabnie przenośne między Mac OS Catalina, Ubuntu 16 i Centos 7, więc zdecydowałem się to zrobić z wbudowanym Pythonem i działało dobrze dla moich skryptów bash.
Odpowiedzi:
posługiwać się:
aby pobrać wszystkie pliki lub
wyświetlić pełną ścieżkę (jeśli ważna jest ścieżka względna)
źródło
$(pwd)
zamiast$PWD
? (tak, wiem, żepwd
jest wbudowany)Spróbuj
realpath
.Aby uniknąć rozwijania linków symbolicznych, użyj
realpath -s
.Odpowiedź pochodzi z polecenia „ bash / fish polecenie wypisania bezwzględnej ścieżki do pliku ”.
źródło
realpath
nie wydaje się być dostępny w systemie Mac (OS X 10.11 „El Capitan”). :-(realpath
nie wydaje się być również dostępny w CentOS 6brew install coreutils
przyniesierealpath
realpath
jest już obecny. Nie musiałem go instalować osobno.realpath
jest , że jest dostępny na Git for Windows (przynajmniej dla mnie).Jeśli masz zainstalowany pakiet coreutils, możesz ogólnie użyć go
readlink -f relative_file_name
w celu odzyskania absolutnego (z rozwiązanymi wszystkimi dowiązaniami symbolicznymi)źródło
brew install coreutils
. Jednak plik wykonywalny jest poprzedzony przez ag:greadlink -f relative_file_name
UPD Kilka wyjaśnień
"$1"
dirname "$1"
cd "$(dirname "$1")
przechodzimy do tego względnego katalogu i uzyskujemy do niego ścieżkę bezwzględną, uruchamiającpwd
polecenie powłoki$(basename "$1")
echo
toźródło
realpath
lubreadlink -f
zrobić. Na przykład nie działa na ścieżkach, w których ostatni składnik jest dowiązaniem symbolicznym.-P
opcjępwd
polecenia:echo "$(cd "$(dirname "$1")"; pwd -P)/$(basename "$1")"
Głosowałem za wybraną odpowiedzią, ale chciałem podzielić się rozwiązaniem. Wadą jest to, że jest to tylko Linux - spędziłem około 5 minut próbując znaleźć odpowiednik OSX, zanim doszedłem do przepełnienia stosu. Jestem pewien, że tam jest.
W systemie Linux można używać
readlink -e
w połączeniu zdirname
.plony
A potem używasz
dirname
siostry ',basename
aby po prostu uzyskać nazwę plikuplony
Poskładać wszystko do kupy..
plony
Jesteś bezpieczny, jeśli celujesz w katalog,
basename
nic nie zwróci, a skończysz z podwójnymi ukośnikami w ostatecznym wyniku.źródło
dirname
,readlink
, ibasename
. To pomogło mi uzyskać absolutną ścieżkę dowiązania symbolicznego, a nie jego cel./home/GKFX
i piszętouch newfile
, to zanim naciśnę klawisz Enter, możesz dojść do wniosku, że mam na myśli „create / home / GKFX / newfile”, co jest bezwzględną ścieżką do pliku, który jeszcze nie istnieje.Myślę, że jest to najbardziej przenośny:
Nie powiedzie się, jeśli ścieżka nie istnieje.
źródło
dirname
jest podstawowym narzędziem GNU, nie jest wspólne dla wszystkich unixenów, jak sądzę.dirname
to standardowe narzędzie POSIX, patrz tutaj: pubs.opengroup.org/onlinepubs/9699919799/utilities/dirname.html${1##*/}
od jednego dnia, a teraz, kiedy zastąpiłem ten koszbasename "$1"
, wydaje się, że w końcu poprawnie obsługują ścieżki kończące się na /.../..
realpath
jest prawdopodobnie najlepszyAle ...
Początkowe pytanie było bardzo zagmatwane na początku, z przykładem słabo powiązanym z zadanym pytaniem.
Wybrana odpowiedź w rzeczywistości odpowiada na podany przykład, a nie na pytanie w tytule. Pierwsza komenda to odpowiedź (czy naprawdę? Wątpię) i równie dobrze mogłaby działać bez znaku „/”. I nie widzę, co robi drugie polecenie.
Kilka problemów jest mieszanych:
zmiana względnej ścieżki na absolutną, cokolwiek by to oznaczało, prawdopodobnie nic. ( Zazwyczaj, jeśli wydasz takie polecenie, jak
touch foo/bar
nazwa ścieżki,foo/bar
musi istnieć dla Ciebie i prawdopodobnie zostać użyta w obliczeniach, zanim plik zostanie faktycznie utworzony ).może istnieć kilka bezwzględnych nazw ścieżek, które oznaczają ten sam plik (lub potencjalny plik), w szczególności z powodu dowiązań symbolicznych (dowiązań symbolicznych) na ścieżce, ale prawdopodobnie z innych powodów (urządzenie może być zamontowane dwa razy jako tylko do odczytu). Można lub nie chcieć rozwiązywać jawności takich dowiązań symbolicznych.
dotarcie do końca łańcucha dowiązań symbolicznych do pliku lub nazwy niebędącej dowiązaniem symbolicznym. To może, ale nie musi, dać absolutną nazwę ścieżki, w zależności od tego, jak jest to zrobione. I można, ale nie trzeba, przekształcić to w absolutną ścieżkę.
Polecenie
readlink foo
bez opcji daje odpowiedź tylko wtedy, gdy jego argumentfoo
jest dowiązanie symboliczne, a ta odpowiedź jest wartością tego dowiązania symbolicznego. Żaden inny link nie jest używany. Odpowiedzią może być ścieżka względna: cokolwiek było wartością argumentu dowiązania symbolicznego.Jednak,
readlink
ma opcje (-f -e lub -m), które będą działać dla wszystkich plików i podadzą jedną bezwzględną ścieżkę dostępu (tę bez dowiązań symbolicznych) do pliku faktycznie oznaczonego przez argument.Działa to dobrze w przypadku wszystkiego, co nie jest dowiązaniem symbolicznym, chociaż można chcieć użyć bezwzględnej nazwy ścieżki bez rozwiązywania pośrednich dowiązań symbolicznych na ścieżce. Odbywa się to za pomocą polecenia
realpath -s foo
W przypadku argumentu dowiązania symbolicznego,
readlink
z jego opcjami ponownie rozwiążemy wszystkie dowiązania symboliczne na bezwzględnej ścieżce do argumentu, ale będzie to również obejmować wszystkie dowiązania symboliczne, które można napotkać, podążając za wartością argumentu. Możesz tego nie chcieć, jeśli chcesz mieć bezwzględną ścieżkę do samego dowodu symbolicznego argumentu, a nie do tego, do czego może ono prowadzić. Ponownie, jeślifoo
jest dowiązaniem symbolicznym,realpath -s foo
otrzyma ścieżkę bezwzględną bez rozpoznawania dowiązań symbolicznych, w tym podanego jako argument.Bez tej
-s
opcjirealpath
robi to samo, coreadlink
poza zwykłym odczytem wartości linku, a także kilkoma innymi rzeczami. Po prostu nie jest dla mnie jasne, dlaczegoreadlink
ma swoje opcje, stwarzając pozornie niepożądaną nadmiarowośćrealpath
.Eksploracja sieci nie mówi nic więcej, z wyjątkiem tego, że mogą występować pewne różnice między systemami.
Wniosek:
realpath
to najlepsza komenda do użycia, z największą elastycznością, przynajmniej do użycia tutaj wymaganego.źródło
Moim ulubionym rozwiązaniem było to przez @EugenKonkov ponieważ nie sugerować obecność innych mediów (pakiet coreutils).
Ale zawiodło dla ścieżek względnych "." i „..”, więc tutaj jest nieco ulepszona wersja obsługująca te specjalne przypadki.
cd
Jednak nadal kończy się niepowodzeniem, jeśli użytkownik nie ma uprawnień do dostępu do katalogu nadrzędnego ścieżki względnej.źródło
Odpowiedź Eugena nie do końca mi odpowiadała, ale tak się stało:
Uwaga dodatkowa, twój bieżący katalog roboczy pozostaje niezmieniony.
źródło
Najlepsze rozwiązanie, imho, to to zamieszczone tutaj: https://stackoverflow.com/a/3373298/9724628 .
Wymaga Pythona do działania, ale wydaje się, że obejmuje wszystkie lub większość przypadków skrajnych i jest bardzo przenośnym rozwiązaniem.
źródło
W przypadku
find
prawdopodobnie najłatwiej jest po prostu podać bezwzględną ścieżkę wyszukiwania, np .:źródło
Jeśli używasz bash w systemie Mac OS X, który ani nie ma realpath, ani jego readlink nie może wydrukować bezwzględnej ścieżki, możesz mieć wybór i musisz zakodować własną wersję, aby ją wydrukować. Oto moja realizacja:
(czysty bash)
(użyj gawk)
(czysty bsd awk)
przykład:
źródło
To, co powiedzieli, z wyjątkiem
find $PWD
lub (w bash),find ~+
jest nieco wygodniejsze.źródło
Podobnie jak odpowiedź @ ernest-a, ale bez wpływu
$OLDPWD
lub definiowania nowej funkcji można uruchomić podpowłokę(cd <path>; pwd)
źródło
Jeśli ścieżka względna jest ścieżką do katalogu, spróbuj mojej, powinna być najlepsza:
źródło
źródło
Ulepszenie do raczej ładnej wersji @ ernest-a:
Rozwiązanie to poprawnie rozwiązuje przypadek, w którym znajduje się ostatni element ścieżki
..
, w którym to przypadku odpowiedź"$(pwd)/$(basename "$1")"
in @ ernest-a pojawi się jakoaccurate_sub_path/spurious_subdirectory/..
.źródło
Jeśli chcesz przekształcić zmienną zawierającą ścieżkę względną w ścieżkę bezwzględną, działa to:
„cd” powtarza echo bez zmiany katalogu roboczego, ponieważ jest wykonywany tutaj w powłoce podrzędnej.
źródło
dir=`cd ".."` && echo $dir
Jest to rozwiązanie łańcuchowe od wszystkich innych, na przykład w przypadku
realpath
niepowodzenia, ponieważ nie jest zainstalowane lub kończy się z kodem błędu, wówczas podejmowane są próby rozwiązania następnego, dopóki nie uzyska właściwej ścieżki.źródło
Możesz użyć podstawienia ciągu bash dla dowolnej ścieżki względnej $ line:
Podstawowe podstawianie początku ciągu jest zgodne ze wzorem
$ {string / # substring / replace},
który jest dobrze omówiony tutaj: https://www.tldp.org/LDP/abs/html/string-manipulation.html
\
Charakter neguje/
, gdy chcemy, aby być częścią łańcucha, które Znajdź / Zamień.źródło
Nie mogłem znaleźć rozwiązania, które byłoby zgrabnie przenośne między Mac OS Catalina, Ubuntu 16 i Centos 7, więc zdecydowałem się to zrobić z wbudowanym Pythonem i działało dobrze dla moich skryptów bash.
źródło