절대 디렉토리 찾기

절대 디렉토리 찾기

시나리오는 다음과 같습니다.

foo/
> data/
> stuff/
> scripts/ -> /.../generic/scripts

어떤 위치(다른 폴더 또는 폴더 내)에서 호출될 때 foo/scripts/bar.sh스크립트를 사용할 수 있기를 원합니다 foo/data.foo/stuff

그러나 방금 사용하면 foo_dir='dirname $0'/..심볼릭 링크가 가리키는 디렉토리로 이동합니다! (그리고 generic대신에 얻으십시오 foo!)

일부 패턴을 사용하여 끝 부분을 먹으면 $0디렉터리 내부에서 스크립트를 호출할 수도 있기 때문에 작동하지 않습니다.

그래서 결국 제가 발견한 유일한 것은 다음과 같은 매우 추악한 것이었습니다.

dir=`dirname $0`
cd $dir
dir=`pwd | sed -r 's_/[^/]+$__'`
cd -

...하지만 더 좋은 방법이 있을 거라고 확신해요, 그렇죠?

내가 사용하는 것은:

dir=$( dirname $( cd `dirname $0`; pwd ) )

완벽할지는 모르겠지만 기대한 만큼의 성능을 발휘하는 것 같습니다.

답변1

다음 한 줄을 사용할 수 있습니다.

DIR="$(cd "$( dirname "$0" )" && pwd )"

답변2

처음으로 질문을 더 자세히 읽지 못해 죄송합니다.

바꾸다:

foo_dir = $(dirname $0)/..

어때요?

foo_dir = $(dirname $(dirname $0))

그러나 이는 $0에 디렉터리 구성 요소가 하나 이상 있는 경우에만 작동합니다. 이 보증이 있습니까?

답변3

예, ..심볼릭 링크의 존재는 실제 문제입니다. 롭 파이크가 썼다.이 주제에 관한 전체 논문.

절대 경로 이름을 ..사용 하지 않는 것이 좋습니다 .dirname

case $0 in
  /*) where="$0" ;;
  *)  where="$(pwd)/$0" ;;
esac
# postcondition: $where is an absolute pathname for script
# N.B $where = .../foo/scripts/command

base="$(dirname "$(dirname "$where")")"
# postcondition: $base = .../foo

resource="$base/data"

나는 실제로 첫 번째 관용구(가능한 상대 경로명에서 절대 경로명을 복원하는 것)를 사용하고 있으며 ~/bin특히 이 목적을 위해 내 디렉토리에 스크립트가 있습니다.

절대 경로 이름을 처리하면 dirname상황이 현명하게 작동합니다.

답변4

귀하의 게시물은 약간 횡설수설하고 일부 진술은 모순되는 것처럼 보이지만 제가 올바르게 이해했다면 귀하는 양식이 있고 $0해당 부분을 foo/scripts/bar.sh추출하려고 하는 것입니다 foo. 또한 경로에 항상 최소한 두 개의 디렉토리가 있도록 보장할 수도 있습니다(만약 그것만 갖고 있다면 bar.sh문제가 됩니다). 그런 다음 경로의 마지막 두 구성 요소를 제거할 수 있습니다.

DIR=${0%/*/*}

그러나 스크립트를 호출하여 이 작업을 수행할 수 있으며 scripts/bar.sh, 이 경우 간단한 패턴 교체는 작동하지 않습니다. 통과는 말할 것도 없고 $PATH조건부로 만들 수도 있습니다.

case $0 in
  */*/*) DIR=${0%/*/*};;
  ?*/*) DIR=.;;
  /*) echo 1>&2 "Storing $0 in the root directory is not supported, aborting."
      exit 125;;
  *) # The script was called through the `PATH`
    IFS=:; set -f; unset DIR
    for d in $PATH; do
      if [ -x "$d/$0" ]; then
        # If you put relative directories in your PATH, you get what you deserve.
        DIR=${d%/*};;
      fi
    done
    if [ -z "$DIR" ]; then
      echo 1>&2 "$0: Fatal error: I can't find myself."
      exit 125
    fi
    unset IFS; set +f;;
esac

관련 정보