심볼릭 링크 없이 상대 경로를 절대 경로로 변환

심볼릭 링크 없이 상대 경로를 절대 경로로 변환

심볼릭 링크를 포함할 수 있는 상대 경로에서 절대(및 정규화된) 경로를 가져오는 Unix 명령이 있습니까?

답변1

당신은 그것을 사용할 수 있습니다readlink유틸리티( -f옵션 포함):

-f, --canonicalize

      canonicalize  by  following  every symlink in every component of
      the given name recursively; all  but  the  last  component  must
      exist

다음을 사용하는 것과 같은 일부 배포판GNU 핵심 도구그리고FreeBSDrealpath(1), 기본적으로 호출만 수행하는 유틸리티 도 함께 제공됩니다.realpath(3)그리고 거의 똑같은 일을 합니다.

답변2

휴대용으로,PWD바꾸다쉘에 의해 현재 디렉토리의 절대 위치로 설정됩니다. 이 경로의 모든 구성 요소는 심볼릭 링크가 될 수 있습니다.

case $f in
  /*) absolute=$f;;
  *) absolute=$PWD/$f;;
esac

.및 를 제거하려면 ..파일이 포함된 디렉터리로 변경하여 $PWD해당 디렉터리로 가져오세요.

if [ -d "$f" ]; then f=$f/.; fi
absolute=$(cd "$(dirname -- "$f")"; printf %s. "$PWD")
absolute=${absolute%?}
absolute=$absolute/${f##*/}

심볼릭 링크를 추적하는 이식 가능한 방법은 없습니다. 디렉토리 경로가 있는 경우 대부분의 unices는 $(cd -- "$dir" && pwd -P 2>/dev/null || pwd)심볼릭 링크를 사용하지 않고 경로를 제공합니다. 심볼릭 링크를 따르는 쉘은 그렇게 하는 경향이 있기 때문입니다 pwd -P("P"는 "물리적"을 나타냄).

일부 유니스는 파일의 "물리적" 경로를 인쇄하는 유틸리티를 제공합니다.

  • 최신 Linux 시스템(GNU coreutils 또는 BusyBox 포함)에는readlink -f, FreeBSD ≥8.3, NetBSD ≥4.0 및 OpenBSD 2.2의 경우에도 마찬가지입니다.
  • FreeBSD ≥4.3 예realpath(일부 Linux 시스템에도 존재하며 BusyBox에 있습니다).
  • Perl을 사용할 수 있는 경우 다음을 사용할 수 있습니다.Cwd기준 치수.

    perl -MCwd -e 'print Cwd::realpath($ARGV[0])' path/to/file
    

답변3

pwd귀하의 요구에 적합합니까? 현재 디렉터리의 절대 경로를 제공합니다. 아니면 당신이 원하는 것은 아마도실제 경로().

답변4

여기에 있는 다른 답변은 좋지만 내 요구 사항에는 충분하지 않습니다. 모든 컴퓨터의 스크립트에서 사용할 수 있는 솔루션이 필요합니다. 내 해결책은 필요한 스크립트에서 호출할 수 있는 쉘 스크립트를 작성하는 것이었습니다.

#!/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

이 솔루션은 이식성을 위해 Bourne Shell용으로 작성되었습니다. "respath.sh"라는 스크립트에 넣었습니다.

스크립트는 다음과 같이 사용할 수 있습니다.

respath.sh '/path/to/file'

아니면 이렇게

respath.sh '/relative/path/here' '/path/to/resolve/relative/to'

스크립트는 두 번째 인수의 경로를 시작점으로 사용하여 첫 번째 인수의 경로를 구문 분석합니다. 첫 번째 인수만 제공되면 스크립트는 현재 작업 디렉터리를 기준으로 경로를 확인합니다.

관련 정보