Odpowiedzi:
Możesz użyć readlink
narzędzia z -f
opcją:
-f, --canonicalize
canonicalize by following every symlink in every component of the given name recursively; all but the last component must exist
Niektóre dystrybucje, na przykład te, które używają GNU coreutils i FreeBSD , również zawierają realpath(1)
narzędzie, które po prostu wywołuje realpath(3)
i robi prawie to samo.
readlink
nor realpath
- w szczególności Solaris i HP-UX.
brew install coreutils
apple.stackexchange.com/a/69332/23040 , a jeśli nie chcesz wykonać kroku przekierowującego wszystkie standardowe narzędzia Mac CLI do nowo zainstalowanych odpowiedników GNU, po prostu zadzwoń greadlink
.
Przenośnie, PWD
zmienna jest ustawiana przez powłokę na jedną bezwzględną lokalizację bieżącego katalogu. Każdy element tej ścieżki może być dowiązaniem symbolicznym.
case $f in
/*) absolute=$f;;
*) absolute=$PWD/$f;;
esac
Jeśli chcesz, aby wyeliminować .
i ..
jak dobrze, przejdź do katalogu zawierającego plik i uzyskać $PWD
tam:
if [ -d "$f" ]; then f=$f/.; fi
absolute=$(cd "$(dirname -- "$f")"; printf %s. "$PWD")
absolute=${absolute%?}
absolute=$absolute/${f##*/}
Nie ma przenośnego sposobu na śledzenie dowiązań symbolicznych. Jeśli masz ścieżkę do katalogu, w większości jednorożców $(cd -- "$dir" && pwd -P 2>/dev/null || pwd)
zapewnia ścieżkę, która nie używa dowiązań symbolicznych, ponieważ powłoki, które śledzą dowiązania symboliczne, mają tendencję do implementowania pwd -P
(„P” dla „fizycznego”).
Niektóre jednorożce zapewniają narzędzie do drukowania „fizycznej” ścieżki do pliku.
readlink -f
, podobnie jak FreeBSD ≥ 8.3, NetBSD ≥4,0 i OpenBSD już w wersji 2.2.realpath
(jest także obecny na niektórych systemach Linux i jest w BusyBox).Jeśli Perl jest dostępny, możesz użyć Cwd
modułu .
perl -MCwd -e 'print Cwd::realpath($ARGV[0])' path/to/file
pwd
( $(cd -- "$dir" && pwd -P 2>/dev/null | pwd)
)? Wygląda na to, że nie obchodzi to standardowe wyjście.
||
Czy pwd
pasuje do twoich potrzeb? Podaje bezwzględną ścieżkę do bieżącego katalogu. A może to, czego chcesz, to realpath () .
alister
i rss67
w tym artykule przedstawiam najbardziej stabilny, kompatybilny i najłatwiejszy sposób. Nigdy przedtem nie widziałem lepszego sposobu.
RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
Jeśli chcesz wrócić do pierwotnej lokalizacji,
ORGPATH=`pwd`
RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
cd $ORGPATH
lub
RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
cd -
Chciałbym, żeby to pomogło. To było dla mnie najlepsze rozwiązanie.
ABSPATH=$(cd -- "$RELPATH" && pwd)
. Zwróć uwagę na podwójne cudzysłowy wokół podstawienia (aby nie łamać, jeśli ścieżka zawiera białe znaki i znaki globowania) oraz --
(w przypadku, gdy ścieżka zaczyna się od -
). Działa to również tylko w przypadku katalogów i nie kanonizuje dowiązań symbolicznych zgodnie z żądaniem. Zobacz moją odpowiedź, aby uzyskać więcej informacji.
Inne odpowiedzi tutaj były w porządku, ale były niewystarczające dla moich potrzeb. Potrzebowałem rozwiązania, którego mógłbym użyć w moich skryptach na dowolnym komputerze. Moim rozwiązaniem było napisanie skryptu powłoki, który można wywoływać ze skryptów tam, gdzie są potrzebne.
#!/bin/sh
if [ $# -eq 0 ] || [ $# -gt 2 ]; then
printf 'Usage: respath path [working-directory]\n' >&2
exit 1
fi
cantGoUp=
path=$1
if [ $# -gt 1 ]; then
cd "$2"
fi
cwd=`pwd -P` #Use -P option to account for directories that are actually symlinks
#Handle non-relative paths, which don't need resolution
if echo "$path" | grep '^/' > /dev/null ; then
printf '%s\n' "$path"
exit 0
fi
#Resolve for each occurrence of ".." at the beginning of the given path.
#For performance, don't worry about ".." in the middle of the path.
while true
do
case "$path" in
..*)
if [ "$cwd" = '/' ]; then
printf 'Invalid relative path\n' >&2
exit 1
fi
if [ "$path" = '..' ]; then
path=
else
path=`echo "$path" | sed 's;^\.\./;;'`
fi
cwd=`dirname $cwd`
;;
*)
break
;;
esac
done
cwd=`echo "$cwd" | sed 's;/$;;'`
if [ -z "$path" ]; then
if [ -z "$cwd" ]; then
cwd='/'
fi
printf '%s\n' "$cwd"
else
printf '%s/%s\n' "$cwd" "$path"
fi
To rozwiązanie zostało napisane dla Bourne Shell pod kątem przenośności. Mam to w skrypcie o nazwie „respath.sh”.
Tego skryptu można użyć w następujący sposób:
respath.sh '/path/to/file'
Lub tak
respath.sh '/relative/path/here' '/path/to/resolve/relative/to'
Skrypt rozwiązuje ścieżkę w pierwszym argumencie, używając ścieżki z drugiego argumentu jako punktu początkowego. Jeśli podano tylko pierwszy argument, skrypt rozpoznaje ścieżkę względem bieżącego katalogu roboczego.
pwd
wbudowaną i nie obsługuje -P
(powłoka Bourne'a nie implementuje tej logicznej obsługi $ PWD jak powłoki POSIX).
cd -P --
jeśli pierwszy argument zawiera trochę ..
case
czek powinien być ..|../*)
zamiast ..*
.
dirname $cwd
Odnosząc się do odpowiedzi wszystkich innych, znalazłem poniższą funkcję, która jest bardzo łatwa i przenośna między Linuksem / MAC OSX niż inne, które znalazłem wszędzie. Może komuś pomóc.
#!/usr/bin/bash
get_absolute_path(){
file_path=`pwd $1`
echo "$file_path/$1"
}
#to assign to a variable
absolute_path=$(get_absolute_path "file.txt")
echo $absolute_path
Załóżmy, że zmienna a przechowuje nazwę ścieżki (a = „cokolwiek”)
1. W przypadku potencjalnej ścieżki zawierającej przestrzeń:
c=$(grep -o " " <<< $a | wc -l); if (( $c > "0" )); then a=$(sed 's/ /\\ /g' <<< $a); fi
2. W przypadku rzeczywistego pytania, tj. Konwersji ścieżki na wartość bezwzględną: readlink może pobrać zawartość dowiązania symbolicznego, które można zastosować w następujący sposób. (uwaga readlink -f
byłaby idealna, ale nie jest dostępna przynajmniej w wersji bash dla Mac OS X, w której -f oznacza FORMATY ).
if [[ $(readlink $a) == "" ]]; then a=$(cd $a; pwd); else a=$(cd $(readlink $a); pwd); fi
3. Właśnie się nauczyłem pwd -P
w man pwd
: -P ma „ Wyświetlić fizyczny bieżący katalog roboczy (wszystkie dowiązania symboliczne rozwiązane) ” i tym samym
if (( $(grep -o " " <<< $a | wc -l) > "0" )); then a=$(sed 's/ /\\ /g' <<< $a); fi; a=$(cd $a; pwd -P)
też będzie działać.
Wniosek: połącz 1 z 2, aby spełnić oba wymagania, a nazwy ścieżek zawierających spację zostały już omówione w bardziej zwięzłym 3 .
-f
Przełącznik nie istnieje w systemie Mac OS X (co najmniej od 10.8.5). Bez-f
przełącznika po prostu zwraca kod błędu.