zsh에서 스크립트의 절대 경로를 얻는 Unix 휴대용 방법은 무엇입니까?

zsh에서 스크립트의 절대 경로를 얻는 Unix 휴대용 방법은 무엇입니까?

(zsh) 스크립트가 절대 경로를 결정하는 이식 가능한1 방법 은 무엇입니까 ?

Linux에서는 다음과 같은 것을 사용합니다.

mypath=$(readlink -f $0)

...하지만 휴대할 수는 없습니다. ( readlink예를 들어 다윈은 이 기호를 인식하지 못했고 -f이에 상응하는 기호도 없습니다.) (또한 readlink이를 위해 이를 사용하는 것은 다소 모호해 보이는 해킹입니다.)

이식 가능한 방법이 더 있나요?


1 즉, Unix 운영 체제 제품군 전체에 걸쳐 이식 가능합니다.

답변1

zsh에서는 다음을 수행할 수 있습니다.

mypath=${0:a}

또는 스크립트가 있는 디렉터리를 가져옵니다.

mydir=${0:a:h}

바라보다기록 확장 수정자에 대한 Zsh 문서정보 문서가 설치된 경우 man zshexpn로컬로 표시됩니다 .info -f zsh -n Modifiers

답변2

의 경우 zsh다음과 같습니다.

mypath=$0:A

또는

mypath=$0:P

최신 버전에서는 (참조수동어떻게 다른지 자세히 알아보세요.)

이제 다른 셸의 경우 realpath()readlink()는 표준 기능(후자는 시스템 호출)이지만 표준 명령은 realpath아니지만 readlink일부 시스템에는 서로 다른 동작과 기능 세트가 있거나 둘 다 있습니다.

일반적으로 이식성을 위해 다음을 사용할 수 있습니다 perl.

abs_path() {
  perl -MCwd -le '
    for (@ARGV) {
      if ($p = Cwd::abs_path $_) {
        print $p;
      } else {
        warn "abs_path: $_: $!\n";
        $ret = 1;
      }
    }
    exit $ret' "$@"
}

readlink -f파일의 디렉터리 이름이 존재하지 않는 한 불평하지 않는다는 점 에서 realpath()(GNU)보다 GNU처럼 동작합니다 .readlink -e

답변3

나는 몇 년 동안 그것을 사용해 왔습니다:

# The absolute, canonical ( no ".." ) path to this script
canonical=$(cd -P -- "$(dirname -- "$0")" && printf '%s\n' "$(pwd -P)/$(basename -- "$0")")

답변4

절대 경로, 즉 루트 디렉터리의 경로를 의미한다고 가정합니다.

case $0 in
  /*) mypath=$0;;
  *) mypath=$PWD/$0;;
esac

그건 그렇고, 이것은 모든 Bourne 스타일 쉘에서 작동합니다.

모든 심볼릭 링크가 해결된 경로를 의미한다면 이야기는 다릅니다. readlink -fLinux(일부 단순화된 BusyBox 시스템 제외), FreeBSD, NetBSD, OpenBSD 및 Cygwin에서는 작동하지만 OS/X, AIX, HP/UX 또는 Solaris에서는 작동하지 않습니다. 있는 경우 readlink루프에서 호출할 수 있습니다.

realpath () {
  [ -e "$1" ] || return
  case $1 in
    /*) :;;
    *) set "$PWD/$1";;
  esac
  while [ -L "$1" ]; do
    set "${1%/*}" "$(readlink "$1")"
    case $2 in
      /*) set "$2";;
      *) if [ -z "$1" ]; then set "/$2"; else set "$(cd "$1" && pwd -P)/$2"; fi;;
    esac
  done
  case $1 in
    */.|*/..) set "$(cd "$1" && pwd -P)";;
    */./*|*/../*) set "$(cd "${1%/*}" && pwd -P)/${1##*/}"
  esac
  realpath=$1
}

그렇지 않은 경우 readlink근사치를 사용할 수 있지만 ls -n이는 ls파일 이름에서 인쇄할 수 없는 문자를 분리하지 않는 경우에만 작동합니다.

poor_mans_readlink () {
  if [ -L "$1" ]; then
    set -- "$1" "$(LC_ALL=C command ls -n -- "$2"; echo z)"
    set -- "${2%??}"
    set -- "${2#*"$1 -> "}"
  fi
  printf '%s\n' "$1"
}

(추가적인 z경우는 링크 대상이 개행 문자로 끝나는 경우입니다. 그렇지 않으면 명령 대체가 소진됩니다. realpath참고로 이 함수는 디렉토리 이름에 대해 이 경우를 처리하지 않습니다.)

관련 정보