Linux에서 readlink
유틸리티는 -f
추가 링크를 따르는 옵션 을 허용합니다 . Mac 및 BSD 기반 시스템에서는 작동하지 않는 것 같습니다. 동등한 것은 무엇입니까?
디버그 정보는 다음과 같습니다.
$ which readlink; readlink -f
/usr/bin/readlink
readlink: illegal option -f
usage: readlink [-n] [file ...]
답변
readlink -f
두 가지 일을한다 :
- 실제 파일을 찾을 때까지 일련의 심볼릭 링크를 반복합니다.
- 파일의 정규화 된 이름, 즉 절대 경로 이름을 반환합니다 .
원하는 경우 바닐라 읽기 링크 동작을 사용하여 동일한 작업을 수행하는 쉘 스크립트를 작성할 수 있습니다. 다음은 예입니다. 분명히 당신은 당신이 전화하고 싶은 자신의 스크립트에 이것을 삽입 할 수 있습니다readlink -f
#!/bin/sh
TARGET_FILE=$1
cd `dirname $TARGET_FILE`
TARGET_FILE=`basename $TARGET_FILE`
# Iterate down a (possible) chain of symlinks
while [ -L "$TARGET_FILE" ]
do
TARGET_FILE=`readlink $TARGET_FILE`
cd `dirname $TARGET_FILE`
TARGET_FILE=`basename $TARGET_FILE`
done
# Compute the canonicalized name by finding the physical path
# for the directory we're in and appending the target file.
PHYS_DIR=`pwd -P`
RESULT=$PHYS_DIR/$TARGET_FILE
echo $RESULT
여기에는 오류 처리가 포함되지 않습니다. 특히 중요한 것은 심볼릭 링크주기를 감지하지 못합니다. 이를 수행하는 간단한 방법은 루프를 돌아 다니는 횟수를 세고 1,000과 같이 엄청나게 큰 숫자를 칠 경우 실패하는 것입니다.
pwd -P
대신 사용하도록 편집 했습니다 $PWD
.
이 스크립트는 GNU readlink 와 같이 사용 하려면 ./script_name filename
, no -f
,로 변경 $1
해야 $2
합니다 -f filename
.
답변
MacPorts 및 Homebrew는 (GNU readlink)를 포함 하는 coreutils 패키지를 제공합니다 greadlink
. mackb.com의 Michael Kallweitt 게시물
brew install coreutils
greadlink -f file.txt
답변
realpath(3)
, 또는 Python에 관심이있을 수 있습니다 os.path.realpath
. 둘은 정확히 같지 않습니다. C 라이브러리 호출에는 중개 경로 구성 요소가 있어야하지만 Python 버전에는 없습니다.
$ pwd
/tmp/foo
$ ls -l
total 16
-rw-r--r-- 1 miles wheel 0 Jul 11 21:08 a
lrwxr-xr-x 1 miles wheel 1 Jul 11 20:49 b -> a
lrwxr-xr-x 1 miles wheel 1 Jul 11 20:49 c -> b
$ python -c 'import os,sys;print(os.path.realpath(sys.argv[1]))' c
/private/tmp/foo/a
다른 스크립팅 언어보다 가벼운 것을 선호한다고 말했지만 바이너리를 컴파일 할 수없는 경우를 대비하여 Python 및 ctypes (Mac OS X 10.5에서 사용 가능)를 사용하여 라이브러리 호출을 래핑 할 수 있습니다.
#!/usr/bin/python
import ctypes, sys
libc = ctypes.CDLL('libc.dylib')
libc.realpath.restype = ctypes.c_char_p
libc.__error.restype = ctypes.POINTER(ctypes.c_int)
libc.strerror.restype = ctypes.c_char_p
def realpath(path):
buffer = ctypes.create_string_buffer(1024) # PATH_MAX
if libc.realpath(path, buffer):
return buffer.value
else:
errno = libc.__error().contents.value
raise OSError(errno, "%s: %s" % (libc.strerror(errno), buffer.value))
if __name__ == '__main__':
print realpath(sys.argv[1])
아이러니하게도이 스크립트의 C 버전은 더 짧아야합니다. 🙂
답변
나는 또 다른 구현에 더미 싫지만)는 필요 휴대용, 순수한 쉘 구현 하고, b)는 단위 테스트 범위 , 이런 일에 대한 가장자리 케이스의 수만큼 사소하지 않은 .
테스트 및 전체 코드 는 Github 프로젝트를 참조하십시오 . 다음은 구현의 개요입니다.
키이스 스미스 (Keith Smith)는 다음과 같이 지적한다 readlink -f
. 1) 심볼릭 링크를 재귀 적으로 해결하고 2) 결과를 정규화한다
realpath() {
canonicalize_path "$(resolve_symlinks "$1")"
}
먼저 symlink resolver 구현 :
resolve_symlinks() {
local dir_context path
path=$(readlink -- "$1")
if [ $? -eq 0 ]; then
dir_context=$(dirname -- "$1")
resolve_symlinks "$(_prepend_path_if_relative "$dir_context" "$path")"
else
printf '%s\n' "$1"
fi
}
_prepend_path_if_relative() {
case "$2" in
/* ) printf '%s\n' "$2" ;;
* ) printf '%s\n' "$1/$2" ;;
esac
}
이것은 전체 구현 의 약간 단순화 된 버전입니다 . 전체 구현은 symlink주기에 대한 작은 검사를 추가 하고 출력을 약간 마사지합니다.
마지막으로 경로를 표준화하는 기능 :
canonicalize_path() {
if [ -d "$1" ]; then
_canonicalize_dir_path "$1"
else
_canonicalize_file_path "$1"
fi
}
_canonicalize_dir_path() {
(cd "$1" 2>/dev/null && pwd -P)
}
_canonicalize_file_path() {
local dir file
dir=$(dirname -- "$1")
file=$(basename -- "$1")
(cd "$dir" 2>/dev/null && printf '%s/%s\n' "$(pwd -P)" "$file")
}
그게 다야. 스크립트에 붙여 넣기는 간단하지만 사용 사례에 대한 단위 테스트가없는 코드에 의존하기에는 까다로울 수 있습니다.
답변
외부 의존성없이 거의 모든 곳에서 작동하는 펄의 간단한 1 라이너.
perl -MCwd -e 'print Cwd::abs_path shift' ~/non-absolute/file
심볼릭 링크를 역 참조합니다.
스크립트 사용법은 다음과 같습니다.
readlinkf(){ perl -MCwd -e 'print Cwd::abs_path shift' "$1";}
ABSPATH="$(readlinkf ./non-absolute/file)"
답변
- 사제 설치
- “brew install coreutils”를 실행하십시오.
- “greadlink -f path”를 실행하십시오.
greadlink는 -f를 구현하는 gnu readlink입니다. 당신은 macports 또는 다른 사람도 사용할 수 있습니다, 나는 homebrew를 선호합니다.
답변
나는 개인적으로 realpath라는 스크립트를 만들었습니다.
#!/usr/bin/env python
import os.sys
print os.path.realpath(sys.argv[1])