Jak rozwiązywać dowiązania symboliczne w skrypcie powłoki
Biorąc pod uwagę ścieżkę bezwzględną lub względną (w systemie Uniksopodobnym), chciałbym określić pełną ścieżkę docelową po rozwiązaniu wszelkich pośrednich dowiązań symbolicznych. Punkty bonusowe za jednocześnie rozwiązywanie zapisów ~username.
Jeśli celem jest katalog, może być możliwe, aby chdir() do katalogu, a następnie wywołać getcwd (), ale naprawdę chcę to zrobić ze skryptu powłoki, a nie pisania helpera C. Niestety, muszle mają tendencję do próbowania Ukryj istnienie dowiązań symbolicznych przed użytkownikiem (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
$
Chcę funkcji resolve() takiej, że gdy zostanie wykonana z katalogu tmp w powyższym przykładzie, resolve("foo") == "/Users/greg/tmp/bar".
19 answers
Zgodnie ze standardami, {[0] } powinna zwracać ścieżkę z rozwiązanymi dowiązaniami symbolicznymi.
C Funkcja char *getcwd(char *buf, size_t size)
z unistd.h
powinna mieć takie samo zachowanie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-21 18:41:11
readlink -f "$path"
Uwaga wydawcy: powyższe działa z GNU readlink
i FreeBSD / PC-BSD / OpenBSD readlink
, ale nie {[19] } na OS X od 10.11.
GNU readlink
oferuje dodatkowe, powiązane opcje, takie jak -m
do rozwiązywania dowiązania symbolicznego, niezależnie od tego, czy istnieje ostateczny cel.
Uwaga od wersji GNU coreutils 8.15 (2012-01-06) dostępny jest program realpath, który jest mniej rozbudowany i bardziej elastyczny niż powyższy. Jest również kompatybilny z Utilem FreeBSD o tej samej nazwie. Zawiera również funkcję generowania względnej ścieżki między dwoma plikami.
realpath $path
[admin Dodany poniżej z komentarza przez halloleo -danorton]
Dla Mac OS X (przez co najmniej 10.11.x), Użyj readlink
bez opcji -f
:
readlink $path
Uwaga redaktora: to nie rozwiąże dowiązań symbolicznych rekurencyjnie, a tym samym nie zgłosi docelowego ultimate ; np. given dowiązania symbolicznego a
to wskazuje na b
, co z kolei wskazuje na c
, to tylko raportuje b
(i nie zapewnia, że jest to wyjście jako ścieżka absolutna).
Użyj następującego polecenia perl
w systemie OS X, aby wypełnić lukę brakującej funkcji readlink -f
:perl -MCwd -le 'print Cwd::abs_path(shift)' "$path"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-22 22:46:51
"pwd-P" wydaje się działać, jeśli chcesz tylko katalog, ale jeśli z jakiegoś powodu chcesz nazwę rzeczywistego pliku wykonywalnego, nie sądzę, że to pomaga. Oto moje rozwiązanie:
#!/bin/bash
# get the absolute path of the executable
SELF_PATH=$(cd -P -- "$(dirname -- "$0")" && pwd -P) && SELF_PATH=$SELF_PATH/$(basename -- "$0")
# resolve symlinks
while [[ -h $SELF_PATH ]]; do
# 1) cd to directory of the symlink
# 2) cd to the directory of where the symlink points
# 3) get the pwd
# 4) append the basename
DIR=$(dirname -- "$SELF_PATH")
SYM=$(readlink "$SELF_PATH")
SELF_PATH=$(cd "$DIR" && cd "$(dirname -- "$SYM")" && pwd)/$(basename -- "$SYM")
done
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-18 13:24:01
Jednym z moich ulubionych jest realpath foo
realpath - return the canonicalized absolute pathname realpath expands all symbolic links and resolves references to '/./', '/../' and extra '/' characters in the null terminated string named by path and stores the canonicalized absolute pathname in the buffer of size PATH_MAX named by resolved_path. The resulting path will have no symbolic link, '/./' or '/../' components.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-04 23:39:05
readlink -e [filepath]
Wydaje się być dokładnie tym, o co prosisz - przyjmuje ścieżkę arbir, rozwiązuje wszystkie dowiązania symboliczne i zwraca ścieżkę "rzeczywistą" - i to jest "standard * nix", że prawdopodobnie wszystkie systemy mają już
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-09 14:34:38
Inny sposób:
# Gets the real path of a link, following all links
myreadlink() { [ ! -h "$1" ] && echo "$1" || (local link="$(expr "$(command ls -ld -- "$1")" : '.*-> \(.*\)$')"; cd $(dirname $1); myreadlink "$link" | sed "s|^\([^/].*\)\$|$(dirname $1)/\1|"); }
# Returns the absolute path to a command, maybe in $PATH (which) or not. If not found, returns the same
whereis() { echo $1 | sed "s|^\([^/].*/.*\)|$(pwd)/\1|;s|^\([^/]*\)$|$(which -- $1)|;s|^$|$1|"; }
# Returns the realpath of a called command.
whereis_realpath() { local SCRIPT_PATH=$(whereis $1); myreadlink ${SCRIPT_PATH} | sed "s|^\([^/].*\)\$|$(dirname ${SCRIPT_PATH})/\1|"; }
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-13 10:52:44
Złożenie niektórych z podanych rozwiązań razem, wiedząc, że readlink jest dostępny na większości systemów, ale wymaga innych argumentów, działa to dobrze dla mnie na OSX i Debianie. Nie jestem pewien co do systemów BSD. Może warunek musi być [[ $OSTYPE != darwin* ]]
, aby wykluczyć -f
tylko z OSX.
#!/bin/bash
MY_DIR=$( cd $(dirname $(readlink `[[ $OSTYPE == linux* ]] && echo "-f"` $0)) ; pwd -P)
echo "$MY_DIR"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-14 07:47:17
Oto jak można uzyskać rzeczywistą ścieżkę do pliku w systemie MacOS / Unix za pomocą wbudowanego skryptu Perla:
FILE=$(perl -e "use Cwd qw(abs_path); print abs_path('$0')")
Podobnie, aby uzyskać katalog symbolicznego pliku:
DIR=$(perl -e "use Cwd qw(abs_path); use File::Basename; print dirname(abs_path('$0'))")
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-30 03:57:48
Czy Twoja ścieżka jest katalogiem, czy może plikiem? Jeśli jest to katalog, to jest to proste:
(cd "$DIR"; pwd -P)
Jednak, jeśli to może być plik, to nie zadziała:
DIR=$(cd $(dirname "$FILE"); pwd -P); echo "${DIR}/$(readlink "$FILE")"
Ponieważ dowiązanie symboliczne może zostać rozdzielone na ścieżkę względną lub pełną.
Na skryptach muszę znaleźć prawdziwą ścieżkę, aby móc odwołać się do konfiguracji lub innych skryptów zainstalowanych razem z nim, używam tego:
SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
SOURCE="$(readlink "$SOURCE")"
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
done
Można ustawić SOURCE
na dowolną ścieżkę do pliku. Zasadniczo, tak długo, jak ścieżka jest dowiązaniem symbolicznym, rozwiązuje ten dowiązanie symboliczne. Sztuczka jest w ostatniej linii pętli. Jeśli rozwiązane dowiązanie symboliczne jest bezwzględne, użyje go jako SOURCE
. Jednak, jeśli jest względna, będzie poprzedzać DIR
dla niego, który został rozwiązany w rzeczywistym miejscu przez prosty trick, który pierwszy opisał.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-28 18:00:47
Typowe skrypty powłoki często muszą znaleźć swój katalog "home", nawet jeśli są wywoływane jako dowiązanie symboliczne. Skrypt musi więc znaleźć swoją "prawdziwą" pozycję już od $0.
cat `mvn`
W moim systemie drukuje skrypt zawierający następujące informacje, które powinny być dobrą wskazówką na to, czego potrzebujesz.
if [ -z "$M2_HOME" ] ; then
## resolve links - $0 may be a link to maven's home
PRG="$0"
# need this for relative symlinks
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG="`dirname "$PRG"`/$link"
fi
done
saveddir=`pwd`
M2_HOME=`dirname "$PRG"`/..
# make it fully qualified
M2_HOME=`cd "$M2_HOME" && pwd`
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-11 11:17:23
function realpath {
local r=$1; local t=$(readlink $r)
while [ $t ]; do
r=$(cd $(dirname $r) && cd $(dirname $t) && pwd -P)/$(basename $t)
t=$(readlink $r)
done
echo $r
}
#example usage
SCRIPT_PARENT_DIR=$(dirname $(realpath "$0"))/..
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-10 14:52:57
Uwaga: uważam, że jest to solidne, przenośne, gotowe rozwiązanie, które jest niezmiennie długie właśnie z tego powodu.
Poniżej znajduje się W Pełni zgodny z POSIX skrypt / funkcja , czyli wieloplatformowy (działa również na macOS, którego readlink
nadal nie obsługuje -f
od wersji 10.12 (Sierra))-używa tylko funkcji języka powłoki POSIX i tylko wywołań narzędzi zgodnych z POSIX.
Jest to przenośny implementacja GNU readlink -e
(bardziej rygorystyczna wersja readlink -f
).
Możesz uruchomić skrypt Z sh
lub źródło funkcja W bash
, ksh
, oraz zsh
:
Na przykład wewnątrz skryptu można użyć go w następujący sposób, aby uzyskać prawdziwy katalog źródłowy uruchomionego skryptu z rozwiązanymi dowiązaniami symbolicznymi:
trueScriptDir=$(dirname -- "$(rreadlink "$0")")
rreadlink
definicja skryptu / funkcji:
kod został zaadaptowany z wdzięcznością z ta odpowiedź .
Stworzyłem również autonomiczną wersję narzędzia bash
tutaj , którą można zainstalować za pomocąnpm install rreadlink -g
, jeśli masz węzeł.js zainstalowany.
#!/bin/sh
# SYNOPSIS
# rreadlink <fileOrDirPath>
# DESCRIPTION
# Resolves <fileOrDirPath> to its ultimate target, if it is a symlink, and
# prints its canonical path. If it is not a symlink, its own canonical path
# is printed.
# A broken symlink causes an error that reports the non-existent target.
# LIMITATIONS
# - Won't work with filenames with embedded newlines or filenames containing
# the string ' -> '.
# COMPATIBILITY
# This is a fully POSIX-compliant implementation of what GNU readlink's
# -e option does.
# EXAMPLE
# In a shell script, use the following to get that script's true directory of origin:
# trueScriptDir=$(dirname -- "$(rreadlink "$0")")
rreadlink() ( # Execute the function in a *subshell* to localize variables and the effect of `cd`.
target=$1 fname= targetDir= CDPATH=
# Try to make the execution environment as predictable as possible:
# All commands below are invoked via `command`, so we must make sure that
# `command` itself is not redefined as an alias or shell function.
# (Note that command is too inconsistent across shells, so we don't use it.)
# `command` is a *builtin* in bash, dash, ksh, zsh, and some platforms do not
# even have an external utility version of it (e.g, Ubuntu).
# `command` bypasses aliases and shell functions and also finds builtins
# in bash, dash, and ksh. In zsh, option POSIX_BUILTINS must be turned on for
# that to happen.
{ \unalias command; \unset -f command; } >/dev/null 2>&1
[ -n "$ZSH_VERSION" ] && options[POSIX_BUILTINS]=on # make zsh find *builtins* with `command` too.
while :; do # Resolve potential symlinks until the ultimate target is found.
[ -L "$target" ] || [ -e "$target" ] || { command printf '%s\n' "ERROR: '$target' does not exist." >&2; return 1; }
command cd "$(command dirname -- "$target")" # Change to target dir; necessary for correct resolution of target path.
fname=$(command basename -- "$target") # Extract filename.
[ "$fname" = '/' ] && fname='' # !! curiously, `basename /` returns '/'
if [ -L "$fname" ]; then
# Extract [next] target path, which may be defined
# *relative* to the symlink's own directory.
# Note: We parse `ls -l` output to find the symlink target
# which is the only POSIX-compliant, albeit somewhat fragile, way.
target=$(command ls -l "$fname")
target=${target#* -> }
continue # Resolve [next] symlink target.
fi
break # Ultimate target reached.
done
targetDir=$(command pwd -P) # Get canonical dir. path
# Output the ultimate target's canonical path.
# Note that we manually resolve paths ending in /. and /.. to make sure we have a normalized path.
if [ "$fname" = '.' ]; then
command printf '%s\n' "${targetDir%/}"
elif [ "$fname" = '..' ]; then
# Caveat: something like /var/.. will resolve to /private (assuming /var@ -> /private/var), i.e. the '..' is applied
# AFTER canonicalization.
command printf '%s\n' "$(command dirname -- "${targetDir}")"
else
command printf '%s\n' "${targetDir%/}/$fname"
fi
)
rreadlink "$@"
Styczna na bezpieczeństwo:
Jarno , w odniesieniu do funkcji zapewniającej, że builtin command
nie jest zasłonięty przez alias lub funkcję powłoki o tej samej nazwie, pyta w komentarzu:
Co jeśli
unalias
lubunset
i[
są ustawione jako aliasy czy funkcje powłoki?
Motywacją stojącą za rreadlink
zapewnianiem, że command
ma swoje pierwotne znaczenie jest użycie go do ominięcia (łagodnego) wygody aliasów i funkcji często używanych do cieniowania standardowych poleceń w interaktywnych powłokach, takich jak przedefiniowanie ls
w celu włączenia ulubionych opcji.
unalias
lub unset
- lub, while
, do
, ... - bycie przedefiniowanym nie jest problemem.
Istniejecoś 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 redefinicję wbudowanych, a nawet językowych słów kluczowych, jest z natury zagrożeniem bezpieczeństwa (a pisanie paranoidalnego kodu jest trudne w ogóle).
Aby konkretnie odpowiedzieć na twoje obawy:
Funkcja polega na tym, że unalias
i unset
mają swoje pierwotne znaczenie. Ponowne zdefiniowanie ich jako funkcji powłoki w sposób, który zmienia ich zachowanie, byłoby problemem; ponowne zdefiniowanie jako alias jest
nie koniecznie jest to problemem, ponieważ cytowanie (części) nazwy polecenia (np. \unalias
) omija aliasy.
Jednak cytowanie jest Nie opcją dla słów kluczowych shell (while
, for
, if
, do
, ...) i podczas gdy słowa kluczowe powłoki mają pierwszeństwo przed funkcjami powłoki , W bash
i zsh
aliasy mają najwyższy priorytet, więc aby chronić przed redefinicjami słów kluczowych powłoki, musisz uruchomić unalias
z ich nazwami (chociaż w Nie-interaktywne bash
aliasy powłok (takich jak skrypty) są Nie rozwijane domyślnie - tylko jeśli {[35] } jest jawnie wywołane jako pierwsze).
unalias
- jako wbudowany - ma swoje pierwotne znaczenie, musisz najpierw użyć \unset
na nim, co wymaga, abyunset
miało swoje pierwotne znaczenie: {46]}
unset
jest skorupą wbudowany , więc aby mieć pewność, że jest wywoływana jako taka, musisz upewnić się, że sama nie jest przedefiniowana jako funkcja . Podczas gdy można ominąć formularz aliasu za pomocą cytowania, nie można ominąć formularza funkcji powłoki-catch 22.
Tak więc, jeśli nie możesz polegać na unset
, aby mieć jego pierwotne znaczenie, z tego, co mogę powiedzieć, nie ma gwarantowanego sposobu obrony przed wszelkimi złośliwymi redefinicjami.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:03:05
Spróbuj tego:
cd $(dirname $([ -L $0 ] && readlink -f $0 || echo $0))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-29 03:05:19
Ponieważ spotykałem się z tym wiele razy na przestrzeni lat i tym razem potrzebowałem czystej wersji Bash portable, której mógłbym użyć na OSX i Linuksie, poszedłem dalej i napisałem jedną: {]}
Mieszka tutaj Wersja żywa:
Https://github.com/keen99/shell-functions/tree/master/resolve_path
Ale ze względu na tak, oto obecna wersja (uważam, że jest dobrze przetestowana..ale jestem otwarty na opinie!)
Może nie być trudne, aby to działało dla zwykłej powłoki bourne ' a (sh), ale nie próbowałem...Za bardzo lubię $FUNCNAME. :)
#!/bin/bash
resolve_path() {
#I'm bash only, please!
# usage: resolve_path <a file or directory>
# follows symlinks and relative paths, returns a full real path
#
local owd="$PWD"
#echo "$FUNCNAME for $1" >&2
local opath="$1"
local npath=""
local obase=$(basename "$opath")
local odir=$(dirname "$opath")
if [[ -L "$opath" ]]
then
#it's a link.
#file or directory, we want to cd into it's dir
cd $odir
#then extract where the link points.
npath=$(readlink "$obase")
#have to -L BEFORE we -f, because -f includes -L :(
if [[ -L $npath ]]
then
#the link points to another symlink, so go follow that.
resolve_path "$npath"
#and finish out early, we're done.
return $?
#done
elif [[ -f $npath ]]
#the link points to a file.
then
#get the dir for the new file
nbase=$(basename $npath)
npath=$(dirname $npath)
cd "$npath"
ndir=$(pwd -P)
retval=0
#done
elif [[ -d $npath ]]
then
#the link points to a directory.
cd "$npath"
ndir=$(pwd -P)
retval=0
#done
else
echo "$FUNCNAME: ERROR: unknown condition inside link!!" >&2
echo "opath [[ $opath ]]" >&2
echo "npath [[ $npath ]]" >&2
return 1
fi
else
if ! [[ -e "$opath" ]]
then
echo "$FUNCNAME: $opath: No such file or directory" >&2
return 1
#and break early
elif [[ -d "$opath" ]]
then
cd "$opath"
ndir=$(pwd -P)
retval=0
#done
elif [[ -f "$opath" ]]
then
cd $odir
ndir=$(pwd -P)
nbase=$(basename "$opath")
retval=0
#done
else
echo "$FUNCNAME: ERROR: unknown condition outside link!!" >&2
echo "opath [[ $opath ]]" >&2
return 1
fi
fi
#now assemble our output
echo -n "$ndir"
if [[ "x${nbase:=}" != "x" ]]
then
echo "/$nbase"
else
echo
fi
#now return to where we were
cd "$owd"
return $retval
}
Oto klasyczny przykład, dzięki brew:
%% ls -l `which mvn`
lrwxr-xr-x 1 draistrick 502 29 Dec 17 10:50 /usr/local/bin/mvn@ -> ../Cellar/maven/3.2.3/bin/mvn
Użyj tej funkcji, a zwróci-real-path:
%% cat test.sh
#!/bin/bash
. resolve_path.inc
echo
echo "relative symlinked path:"
which mvn
echo
echo "and the real path:"
resolve_path `which mvn`
%% test.sh
relative symlinked path:
/usr/local/bin/mvn
and the real path:
/usr/local/Cellar/maven/3.2.3/libexec/bin/mvn
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-24 21:06:54
Aby obejść niekompatybilność Maca, wymyśliłem
echo `php -r "echo realpath('foo');"`
Nie wielki ale cross OS
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-21 18:43:19
W przypadku, gdy nie można użyć pwd (np. wywołanie skryptu z innej lokalizacji), użyj realpath (z lub bez dirname):
$(dirname $(realpath $PATH_TO_BE_RESOLVED))
Działa zarówno podczas wywołania przez (wiele) dowiązań symbolicznych, jak i podczas bezpośredniego wywołania skryptu-z dowolnego miejsca.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-02-25 13:20:39
Jest to rozwiązywanie dowiązań symbolicznych w Bash, które działa niezależnie od tego, czy dowiązanie jest katalogiem, czy nie:
function readlinks {(
set -o errexit -o nounset
declare n=0 limit=1024 link="$1"
# If it's a directory, just skip all this.
if cd "$link" 2>/dev/null
then
pwd -P
return 0
fi
# Resolve until we are out of links (or recurse too deep).
while [[ -L $link ]] && [[ $n -lt $limit ]]
do
cd "$(dirname -- "$link")"
n=$((n + 1))
link="$(readlink -- "${link##*/}")"
done
cd "$(dirname -- "$link")"
if [[ $n -ge $limit ]]
then
echo "Recursion limit ($limit) exceeded." >&2
return 2
fi
printf '%s/%s\n' "$(pwd -P)" "${link##*/}"
)}
Zauważ, że wszystkie cd
i set
rzeczy odbywają się w subshell.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-05-24 04:22:01
Tutaj przedstawiam to, co uważam za wieloplatformowe (przynajmniej Linux i macOS) rozwiązanie odpowiedzi, która działa dobrze dla mnie obecnie.
crosspath()
{
local ref="$1"
if [ -x "$(which realpath)" ]; then
path="$(realpath "$ref")"
else
path="$(readlink -f "$ref" 2> /dev/null)"
if [ $? -gt 0 ]; then
if [ -x "$(which readlink)" ]; then
if [ ! -z "$(readlink "$ref")" ]; then
ref="$(readlink "$ref")"
fi
else
echo "realpath and readlink not available. The following may not be the final path." 1>&2
fi
if [ -d "$ref" ]; then
path="$(cd "$ref"; pwd -P)"
else
path="$(cd $(dirname "$ref"); pwd -P)/$(basename "$ref")"
fi
fi
fi
echo "$path"
}
Oto macOS (tylko?) rozwiązanie. Prawdopodobnie lepiej pasuje do pierwotnego pytania.
mac_realpath()
{
local ref="$1"
if [[ ! -z "$(readlink "$ref")" ]]; then
ref="$(readlink "$1")"
fi
if [[ -d "$ref" ]]; then
echo "$(cd "$ref"; pwd -P)"
else
echo "$(cd $(dirname "$ref"); pwd -P)/$(basename "$ref")"
fi
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-01-14 10:32:08
Moja odpowiedź tutaj Bash: jak uzyskać prawdziwą ścieżkę dowiązania symbolicznego?
Ale w skrócie bardzo przydatne w skryptach:
script_home=$( dirname $(realpath "$0") )
echo Original script home: $script_home
Są one częścią GNU coreutils, nadającą się do użytku w systemach Linux.
Aby wszystko przetestować, dodajemy dowiązanie symboliczne do /home / test2/, poprawiamy kilka dodatkowych rzeczy i uruchamiamy / wywołujemy z katalogu głównego:
/$ /home/test2/symlink
/home/test
Original script home: /home/test
Gdzie
Original script is: /home/test/realscript.sh
Called script is: /home/test2/symlink
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-03 14:01:43