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


63

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

답변:


79

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 coreutilsFreeBSD 를 사용하는 배포판과 같은 일부 배포판에는 realpath(1)기본적으로 realpath(3)거의 동일한 기능을 수행 하는 유틸리티가 포함되어 있습니다.


16
-f스위치는 맥 OS X (적어도 10.8.5 현재)에 존재하지 않습니다. -f스위치가 없으면 오류 코드 만 반환합니다.
iconoclast

3
일부 시스템도 함께 제공 readlink하거나 realpathSolaris 및 특히 HP-UX, -.
Sildoreth

Mac 문제 : brew install coreutils apple.stackexchange.com/a/69332/23040 및 모든 표준 Mac CLI 도구를 새로 설치된 GNU 도구로 리디렉션하는 단계를 수행하지 않으려면을 호출하십시오 greadlink.
아드리안

18

이식 가능하게 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##*/}

심볼릭 링크를 따르는 휴대용 방법은 없습니다. 디렉토리에 대한 경로가있는 경우 대부분의 유니스 $(cd -- "$dir" && pwd -P 2>/dev/null || pwd)에서는 기호 링크를 추적하는 쉘이 구현하는 경향이 있기 때문에 기호 링크를 사용하지 않는 경로를 제공합니다 pwd -P( "물리적"의 경우 "P").

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

  • 합리적으로 최근의 Linux 시스템 (GNU coreutils 또는 BusyBox 포함)은 readlink -fFreeBSD ≥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

왜 무언가를 pwd( $(cd -- "$dir" && pwd -P 2>/dev/null | pwd))에 파이프 합니까? stdin에 대해서는 신경 쓰지 않는 것 같습니다.
Mateusz Piotrowski 2016 년

1
@MateuszPiotrowski Typo, 나는 글을 쓰려고했다||
Gilles

5

pwd사용자의 요구에 맞는? 현재 디렉토리의 절대 경로를 제공합니다. 또는 원하는 것은 realpath () 입니다.


3

alisterrss67에서 이 문서 가장 안정적인 호환 쉬운 방법 소개합니다. 나는 이것보다 더 나은 방법을 본 적이 없다.

RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`

원래 위치로 돌아가려면

ORGPATH=`pwd`
RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
cd $ORGPATH

또는

RELPATH=./../
cd $RELPATH
ABSPATH=`pwd`
cd -

이것이 도움이되기를 바랍니다. 이것은 저에게 가장 큰 해결책이었습니다.


12
실제로 그렇게 좋은 방법은 아닙니다. 디렉토리를 변경했다가 다시 가져 오는 것은 신뢰할 수 없습니다. 돌아올 수있는 권한이 없거나 그 동안 디렉토리 이름이 변경되었을 수 있습니다. 대신 서브 쉘에서 디렉토리를 변경하십시오 ABSPATH=$(cd -- "$RELPATH" && pwd). 대체 할 때 큰 따옴표 (경로에 공백과 글 로빙 문자가 포함 된 경우 중단되지 않도록)와 --(경로가로 시작하는 경우 )를 유의하십시오 -. 또한 이것은 디렉토리에서만 작동하며 요청에 따라 기호 링크를 정규화하지 않습니다. 자세한 내용은 내 답변을 참조하십시오.
Gilles

"> 당신은 돌아올 수있는 권한이 없을 수 있습니다"당신은 디렉토리에 cd를 의미하지만 CD를 다시 수 없습니다? 예제 시나리오를 제공해 주시겠습니까?
Talespin_Kit

0

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

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

스크립트는 두 번째 인수의 경로를 시작점으로 사용하여 첫 번째 인수의 경로를 분석합니다. 첫 번째 인수 만 제공하면 스크립트는 현재 작업 디렉토리에 상대적인 경로를 분석합니다.


요즘은 Solaris 10 이하 버전에서만 Bourne 쉘을 찾을 수 있습니다. 그건 Bourne의가있다 SVR2 이후 대부분의 Bourne 쉘 구현처럼 (1984) 쉘 pwd내장하고 지원하지 않습니다 -P(Bourne 쉘은 할 POSIX 쉘처럼 취급 논리 $의 PWD를 구현하지 않았다).
Stéphane Chazelas

Bourne 호환성을 떨어 뜨리면 POSIX $ {var ## pattern} 구문을 사용하고 일부 값으로 인해 중단 될 에코를 피할 수 있습니다.
Stéphane Chazelas

cd (및 pwd)의 종료 상태를 확인하는 것을 잊어 버렸습니다. cd -P --첫 번째 논거에 일부 내용이 포함되어있을 경우에도 사용해야 합니다.
Stéphane Chazelas

귀하의 case확인이 있어야한다 ..|../*)대신 ..*.
Stéphane Chazelas

에 따옴표를 누락 한 경우가 있어요dirname $cwd
스테판 Chazelas가

0

또한 $1(일반적으로 ${PWD})에 대한 사전 정의 된 경로가 있는 경우 다음이 작동합니다.

CWD="${1:-${PredefinedAbsolutePath}}"
if [ "${CWD}" != "${PredefinedAbsolutePath}}" ]; then
    case $1 in
        /*) echo "CWD=${CWD}"; ;;
        *) CWD=$(realpath $1); echo "CWD=${CWD}"; ;;
    esac
fi

0

다른 모든 사람들의 대답을 존중하면서, 나는 아래의 기능이 내가 어디에서 찾은 다른 것보다 리눅스 / MAC OSX 사이에서 매우 쉽고 이식 가능하다는 것을 알았습니다. 누군가를 도울 수 있습니다.

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

-1

변수 a 가 경로 이름을 저장 한다고 가정합니다 (a = "whatever")

1. 잠재적 공간 포함 경로의 경우 :

c=$(grep -o " " <<< $a | wc -l); if (( $c > "0" )); then a=$(sed 's/ /\\ /g' <<< $a); fi

2. 실제 질문, 즉 경로를 절대로 변환 : readlink 는 다음과 같이 사용될 수있는 symlink 내용을 검색 할 수 있습니다. (참고 readlink -f는 완벽했지만 적어도 Mac OS X bash에서는 사용할 수 없지만 -fFORMATS를 나타냅니다 .)

if [[ $(readlink $a) == "" ]]; then a=$(cd $a; pwd); else a=$(cd $(readlink $a); pwd); fi

3. 그냥 배운 pwd -Pman pwd: -P "는 것입니다 (모든 심볼릭 링크가 해결) 물리적 현재 작업 디렉토리를 표시 하고, 따라서"

if (( $(grep -o " " <<< $a | wc -l) > "0" )); then a=$(sed 's/ /\\ /g' <<< $a); fi; a=$(cd $a; pwd -P)

작동합니다.

결론 : 공백을 포함하는 경로 이름은 이미보다 간결한 3으로 처리되는 반면 12 를 결합하여 두 요구 사항을 모두 충족시킵니다 .


당신은 잘못 생각합니다. 예를 들어 경로에 위의 공간이 대부분 포함되어 있으면 작동하지 않습니다.
Anthon

또는 때때로 글로브 숯. 그리고 요청 한대로 심볼릭 링크를 해결하지 않습니다.
dave_thompson_085

공백이 포함 된 경로 이름에 대한 "댓글"응답을 삭제하고 "답변"부분을 적절하게 수정했습니다.
vxtal
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.