셸 스크립트에서 심볼릭 링크를 확인하는 방법
(Unix와 유사한 시스템에서) 절대 경로 또는 상대 경로가 주어지면 중간 심볼 링크를 해결한 후 대상의 전체 경로를 결정하고 싶습니다.~사용자 이름 표기법도 동시에 해결할 수 있는 보너스 포인트.
대상이 디렉토리라면 디렉토리에 chdir()를 입력한 다음 getcwd()를 호출할 수도 있지만, C 도우미를 작성하는 것보다 셸 스크립트에서 이 작업을 수행하고 싶습니다.안타깝게도 셸은 사용자에게 심볼릭 링크의 존재를 숨기려고 하는 경향이 있습니다(OS X의 경우 이는 bash입니다).
$ 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
$
내가 원하는 것은 위의 예에서 tmp 디렉토리에서 실행될 때 resolve "foo") == "/Users/greg/tmp/bar"와 같은 함수 해결입니다.
readlink -f "$path"
편집자 참고 사항:위는 GNU와 연동됩니다. readlink
및 FreeBSD/PC-BSD/OpenBSD readlink
그러나 10.11 기준으로 OS X에는 없습니다.
readlink
는) 같추인관가련옵제션공다합과 같은 을 제공합니다.-m
최종 대상의 존재 여부에 관계없이 심볼릭 링크를 해결할 수 있습니다.
GNU 코어 8.15(2012-01-06)를 활용하기 때문에 위보다 덜 둔하고 더 유연한 실제 경로 프로그램이 있습니다.또한 FreeB와 호환됩니다.동일한 이름의 SD 사용률입니다.또한 두 파일 간의 상대 경로를 생성하는 기능도 포함되어 있습니다.
realpath $path
X 10의 경우 Mac OS X 경최(문서 10.11)을 합니다.x를 통해),readlink
없이-f
옵션:
readlink $path
편집자 참고 사항:이렇게 하면 심볼릭 링크가 재귀적으로 해결되지 않으므로 최종 대상을 보고하지 않습니다(예: 심볼릭 링크).a
그것이 가리키는 바는b
그것이 차례로 가리키는 것입니다.c
이은보할것니다입만만 보고됩니다.b
(절대 경로로 출력되는지 확인하지 않습니다.)
의 다음사니를 합니다.perl
에서 명령을 된 OS X의 공백을 .readlink -f
기능:
perl -MCwd -le 'print Cwd::abs_path(shift)' "$path"
, 기에따르면준,면,,pwd -P
심볼 링크가 확인된 경로를 반환해야 합니다.
함수 함char *getcwd(char *buf, size_t size)
unistd.h
같은 행동을 취해야 합니다.
"pwd-P"는 단지 디렉터리를 원한다면 작동하는 것처럼 보이지만, 만약 어떤 이유로 당신이 실제 실행 파일의 이름을 원한다면 저는 그것이 도움이 되지 않습니다.제 솔루션은 다음과 같습니다.
#!/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
내가 가장 좋아하는 것 중 하나는realpath foo
realpath - 정규화된 절대 경로 이름을 반환합니다. realpath는 모든 심볼 링크를 확장하고 경로 및 경로에 의해 이름이 지정된 null 끝 문자열에 있는 '//', '/../' 및 추가 '/' 문자에 대한 참조를 확인합니다.표준화된 절대 경로 이름을 resolved_path로 명명된 크기 PATH_MAX의 버퍼에 저장합니다.결과 경로에 기호 링크, '//' 또는'/..구성 요소
readlink -e [filepath]
정확히 당신이 요구하는 것처럼 보입니다. - 그것은 임의의 경로를 받아들이고, 모든 심볼릭 링크를 해결하고, "실제" 경로를 반환합니다. 그리고 그것은 모든 시스템이 이미 가지고 있을 가능성이 높은 "표준 *nix"입니다.
다른 방법:
# 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|"; }
대부분의 시스템에서 읽기 링크를 사용할 수 있지만 다른 인수가 필요하다는 것을 알고 주어진 솔루션 중 일부를 결합하면 OSX와 Debian에서 잘 작동합니다.BSD 시스템에 대해서는 잘 모르겠습니다.아마도 그 조건은[[ $OSTYPE != darwin* ]]
제외하다-f
OSX에서만 사용할 수 있습니다.
#!/bin/bash
MY_DIR=$( cd $(dirname $(readlink `[[ $OSTYPE == linux* ]] && echo "-f"` $0)) ; pwd -P)
echo "$MY_DIR"
인라인 Perl 스크립트를 사용하여 MacOS/Unix에서 파일의 실제 경로를 가져오는 방법은 다음과 같습니다.
FILE=$(perl -e "use Cwd qw(abs_path); print abs_path('$0')")
마찬가지로, 심볼릭 링크된 파일의 디렉터리를 가져오려면:
DIR=$(perl -e "use Cwd qw(abs_path); use File::Basename; print dirname(abs_path('$0'))")
일반 셸 스크립트는 심볼릭 링크로 호출되더라도 "홈" 디렉토리를 찾아야 하는 경우가 많습니다.따라서 스크립트는 $0에서 "실제" 위치를 찾아야 합니다.
cat `mvn`
시스템에서 다음이 포함된 스크립트를 인쇄합니다. 이는 필요한 항목에 대한 좋은 힌트가 될 것입니다.
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`
경로가 디렉토리입니까, 아니면 파일입니까?디렉터리인 경우 다음과 같이 간단합니다.
(cd "$DIR"; pwd -P)
그러나 파일인 경우에는 작동하지 않습니다.
DIR=$(cd $(dirname "$FILE"); pwd -P); echo "${DIR}/$(readlink "$FILE")"
심볼릭 링크가 상대 경로 또는 전체 경로로 해결될 수 있기 때문입니다.
스크립트에서 실제 경로를 찾아야 구성 또는 함께 설치된 다른 스크립트를 참조할 수 있으므로 다음을 사용합니다.
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
설정할 수 있습니다.SOURCE
파일 경로로 이동합니다.기본적으로 경로가 심볼릭 링크인 한 심볼릭 링크는 해결됩니다.속임수는 루프의 마지막 줄에 있습니다.확인된 심볼릭 링크가 절대적인 경우, 이 심볼릭 링크는 다음과 같이 사용됩니다.SOURCE
그러나 상대적인 경우 다음과 같이 추가됩니다.DIR
처음에 설명한 간단한 속임수로 실제 위치로 해결되었습니다.
pwd를 사용할 수 없는 경우(예: 다른 위치에서 스크립트를 호출하는 경우), realpath(dirname 사용 여부와 상관없이):
$(dirname $(realpath $PATH_TO_BE_RESOLVED))
(여러) 심볼 링크를 통해 호출할 때 또는 임의의 위치에서 스크립트를 직접 호출할 때 모두 작동합니다.
업데이트:
적어도 macOS 13(Ventura) 이후, macOS는 궁극적인 목표(FreeB)에 대한 심볼릭 링크를 따르는 것도 지원합니다.SD는 훨씬 더 오랫동안 지원을 받아왔기 때문에 POSIX 호환 솔루션에 대한 필요성이 상당히 감소했습니다.
그러나 아래 구현된 POSIX 호환 솔루션은 여전히 관심을 가질 수 있습니다.
버전의 및 macOS에서 사용할 수 있습니다.
readlink -f
구현되지 않았습니다.플랫폼 전반에 걸쳐 일관된 동작이 필요합니다.
- 특히.
readlink -f
macOS / FreeB에서SD는 GNU 구현과 동등하지 않습니다(Linux distros에서 볼 수 있음).-f
/ / FreeB 에서는 GNU SD(GNU)에합니다.-e
인 대상의 인목표의강(GNU의 ))의를 의미합니다.-f
최종 대상의 마지막 경로 세그먼트(segment)가 존재하지 않도록 합니다.
- 특히.
아래는 POSIX와 완전히 호환되는 스크립트/함수로 크로스 플랫폼(macOS에서도 작동)입니다.readlink
지원하지 -f
10.12 (Sierra) 기준 - POSIX 셸 언어 기능과 POSIX 호환 유틸리티 호출만 사용합니다.
이것은 GNU의 휴대용 구현체입니다(의 더 엄격한 버전).readlink -f
).
, 및 에서 이 함수를 사용하여 스크립트를 실행하거나 소스를 제공할 수 있습니다.
예를 들어 스크립트 내부에서 다음과 같이 사용하여 실행 중인 스크립트의 참 원본 디렉터리를 가져올 수 있으며 심볼 링크가 확인됩니다.
trueScriptDir=$(dirname -- "$(rreadlink "$0")")
rreadlink
스크립트/함수 정의:
코드는 이 답변에서 감사함을 담아 수정되었습니다.
또한 다음을 만들었습니다.bash
여기에 설치할 수 있는 독립 실행형 유틸리티 버전
npm install rreadlink -g
Node.js가 설치되어 있는 경우
#!/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 "$@"
보안에 대한 접선:
jarno, 내장된 기능과 관련하여.command
동일한 이름의 별칭 또는 셸 함수에 의해 음영 처리되지 않습니다. 코멘트에서 다음과 같이 묻습니다.
면 어쩌지
unalias
또는unset
그리고.[
별칭 또는 셸 함수로 설정됩니까?
뒤에 숨은 동기rreadlink
을 확실히 하기 위해command
원래의 의미는 이를 사용하여 편의 별칭을 우회(배제)하는 것이며, 상호 작용 셸에서 표준 명령을 다시 정의하는 것과 같이 종종 사용되는 함수입니다.ls
즐겨찾기 옵션을 포함합니다.
신뢰할 수 없고 을 다루는 걱정하는 것이 안전하다고 생각합니다.unalias
또는unset
아면니있, 문에어서제그,있,while
,do
- 가 없습니다... - 재되의는것되문않지습다니가제은정▁...다않니습.....
기능이 본래의 의미와 행동을 갖기 위해 의존해야 하는 것이 있습니다 - 그것을 피할 방법은 없습니다.
POSIX와 유사한 셸은 내장된 언어 키워드의 재정의를 허용하며 심지어 언어 키워드도 본질적으로 보안 위험입니다(그리고 편집증적 코드를 작성하는 것은 일반적으로 어렵습니다).
구체적으로 귀하의 우려 사항을 해결하기 위해:
은 이기은다의니다존합에 합니다.unalias
그리고.unset
그들의 본래의 의미를 갖는.동작을 변경하는 방식으로 셸 함수로 재정의하는 것은 문제가 될 수 있습니다. 명령 이름(예: 일부)을 따옴표로 묶기 때문에 별칭으로 재정의하는 것은 문제가 되지 않습니다.\unalias
별칭을 합니다. 별칭을 무시합니다.
그러나 견적은 셸 키워드에 대한 옵션이 아닙니다.while
,for
,if
,do
...) 및 셸 키워드가 셸 함수보다 우선하지만,bash
그리고.zsh
우선 높기 때문에 에 대한 하려면 를 해야 .unalias
그들의 이름으로 (비록 공격적이지만). bash
셸(스크립트 등) 별칭은 기본적으로 확장되지 않습니다.shopt -s expand_aliases
를 먼저 명시적으로 호출합니다.
확실하게 하기 위해unalias
- 의미가 에 - 원본의있 - 가로므사합니다야용을 해야 합니다.\unset
먼그것대해에그, 필니다요합은것저▁that다▁on.unset
본래의 의미는 다음과 같습니다.
unset
는 내장된 셸이므로 이를 호출하려면 셸 자체가 함수로 재정의되지 않도록 해야 합니다.따옴표를 사용하여 별칭 양식을 바이패스할 수 있지만 셸 함수 양식 - 캐치 22는 바이패스할 수 없습니다.
그러므로, 당신이 의지할 수 없는 한.unset
원래의 의미를 갖는다는 것은, 제가 아는 바로는, 모든 악의적인 재정의로부터 방어할 수 있는 보장된 방법이 없습니다.
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"))/..
이것은 Bash의 심볼릭 리졸바로, 링크가 디렉토리인지 디렉토리가 아닌지에 상관없이 작동합니다.
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##*/}"
)}
참로모것은cd
그리고.set
일은 하위 셸에서 발생합니다.
사용해 보십시오.
cd $(dirname $([ -L $0 ] && readlink -f $0 || echo $0))
지난 몇 년간 이런 일을 여러 번 겪었고, 이번에는 OSX와 Linux에서 사용할 수 있는 순수 bash 휴대용 버전이 필요했기 때문에 다음과 같이 썼습니다.
라이브 버전은 다음과 같습니다.
https://github.com/keen99/shell-functions/tree/master/resolve_path
하지만 SO를 위해, 여기 최신 버전이 있습니다(저는 그것이 잘 테스트되었다고 생각합니다.하지만 저는 피드백을 받을 수 있습니다!)
일반 본 쉘(sh)에서 작동하도록 만드는 것은 어렵지 않을 수 있지만, 저는 시도하지 않았습니다...저는 $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
}
여기 양조 덕분에 고전적인 예가 있습니다.
%% 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
이 함수를 사용하면 -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
Mac 비호환성 문제를 해결하기 위해 다음과 같은 방법을 생각해 냈습니다.
echo `php -r "echo realpath('foo');"`
우수하지는 않지만 교차 운영 체제
여기서 저는 현재 잘 작동하고 있는 답변에 대해 크로스 플랫폼(적어도 Linux 및 macOS) 솔루션이라고 생각하는 것을 제시합니다.
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"
}
여기 macOS(전용) 솔루션이 있습니다.원래 질문에 더 적합할 수 있습니다.
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
}
제 대답은 Bash입니다. 어떻게 심볼릭 링크의 실제 경로를 얻을 수 있을까요?
하지만 간단히 말해서 대본에 매우 유용합니다.
script_home=$( dirname $(realpath "$0") )
echo Original script home: $script_home
이는 GNU 코어 유틸리티의 일부로, Linux 시스템에서 사용하기에 적합합니다.
모든 것을 테스트하기 위해 symlink를 /home/test2/에 넣고 몇 가지 추가 사항을 수정한 후 루트 디렉토리에서 실행/호출합니다.
/$ /home/test2/symlink
/home/test
Original script home: /home/test
어디에
Original script is: /home/test/realscript.sh
Called script is: /home/test2/symlink
내2센. 이 함수는 에 이함와 POSIX 환호대소모다포다를 포함할 수 .->
하지만 새 줄이나 탭이 포함된 파일 이름으로 작동하지 않습니다.ls
일반적으로 그것들에 문제가 있습니다.
resolve_symlink() {
test -L "$1" && ls -l "$1" | awk -v SYMLINK="$1" '{ SL=(SYMLINK)" -> "; i=index($0, SL); s=substr($0, i+length(SL)); print s }'
}
은 여서해은책결라고 합니다.file
제공된 심볼릭 링크의 대상만 출력하는 사용자 지정 마법 파일을 포함하는 명령입니다.
이것은 Bash 3.2.57에서 테스트한 최고의 솔루션입니다.
# Read a path (similar to `readlink`) recursively, until the physical path without any links (like `cd -P`) is found.
# Accepts any existing path, prints its physical path and exits `0`, exits `1` if some contained links don't exist.
# Motivation: `${BASH_SOURCE[0]}` often contains links; using it directly to extract your project's path may fail.
#
# Example: Safely `source` a file located relative to the current script
#
# source "$(dirname "$(rreadlink "${BASH_SOURCE[0]}")")/relative/script.sh"
#Inspiration: https://stackoverflow.com/a/51089005/6307827
rreadlink () {
declare p="$1" d l
while :; do
d="$(cd -P "$(dirname "$p")" && pwd)" || return $? #absolute path without symlinks
p="$d/$(basename "$p")"
if [ -h "$p" ]; then
l="$(readlink "$p")" || break
#A link must be resolved from its fully resolved parent dir.
d="$(cd "$d" && cd -P "$(dirname "$l")" && pwd)" || return $?
p="$d/$(basename "$l")"
else
break
fi
done
printf '%s\n' "$p"
}
언급URL : https://stackoverflow.com/questions/7665/how-to-resolve-symbolic-links-in-a-shell-script
'source' 카테고리의 다른 글
왜 "bytes(n)"는 n을 이진 표현으로 변환하는 대신 길이 n 바이트 문자열을 생성합니까? (0) | 2023.05.06 |
---|---|
모든 키 누르기에서 Angular 2 변경 이벤트 (0) | 2023.05.06 |
빈 커밋을 원격으로 푸시하는 중 (0) | 2023.05.06 |
변수 주석이란 무엇입니까? (0) | 2023.05.01 |
RegisterStartupScript와 RegisterClientScriptBlock의 차이점은 무엇입니까? (0) | 2023.05.01 |