programing

현재 작업 디렉토리가 아닌 파일 위치에 기반한 상대 경로

kakaobank 2023. 4. 22. 09:51
반응형

현재 작업 디렉토리가 아닌 파일 위치에 기반한 상대 경로

지정:

some.txt
dir
 |-cat.sh

고양이랑.sh 내용:

cat ../some.txt

후 실행 중"을 실행합니다../cat.sh에 inside inside inside dir합니다../dir/cat.sh로 같은 dir 디렉토리가.작업 디렉토리가 다르기 때문일 것으로 예상됩니다.를 쉽게 수 있는 방법이 요?../some.txtcat.sh

입니다(사용할 수 것은 스크립트의 절대경로입니다).${BASH_SOURCE[0]}으로 이를 하여 부모 와 ""를 cd★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

#!/bin/bash
parent_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )

cd "$parent_path"
cat ../some.text

이것에 의해, 셸 스크립트는 어디에서 기동하는지에 관계없이 동작합니다. '달리다'를 하는 것 이 듭니다./cat.sh에 inside inside inside dir.

이 스크립트는 스크립트를 직접 호출하는 경우(즉, 심볼링크가 아닌 경우)에만 작동합니다.그렇지 않으면 스크립트의 현재 위치를 찾는 것이 조금 더 어려워집니다.

@Martin Konecny의 답변은 효과적인 솔루션을 제공하지만, 그가 언급했듯이 실제 스크립트가 다른 디렉토리에 있는 심볼링크를 통해 호출되지 않는 경우에만 작동합니다.

이 답변에서는 이러한 경우를 다룹니다.이 솔루션심볼링크 또는 심볼링크 체인을 통해 스크립트를 호출할 때도 작동합니다.


Linux/GNU 솔루션:

스크립트가 Linux에서만 실행되어야 하는 경우 또는 GNU가 에 있는 것을 알고 있는 경우$PATH하다, 사용하다readlink -f최종 타깃에 대한 심볼링크를 쉽게 해결합니다.

 scriptDir=$(dirname -- "$(readlink -f -- "$BASH_SOURCE")")

GNU GNU †에해 주세요.readlink풀패스에 .즉, 3가지 옵션이 있습니다.-f )--canonicalize-e )--canonicalize-existing및 , 。-m )--canonicalize-missing - 를 해 주세요.man readlink.
중 수 이 시나리오에서는 3가지 옵션을 -f가장 잘 알려진 곳이기 때문입니다.


멀티(Unix와 같은) 플랫폼 솔루션(POSIX만의 유틸리티 세트를 갖춘 플랫폼 포함):

스크립트가 다음 플랫폼에서 실행되어야 하는 경우:

  • 가지고 있다readlink 「」가 .-f옵션(GNU의 의미에서는 최종 타깃에 대한 심볼링크를 해결합니다) - 예를 들어 macOS.

    • macOS는 이전 버전의 BSD 구현을 사용합니다.readlink; FreeBSD/PC-BSD의 최신 버전은-f.
  • 가지고 있지 않다readlink단, HP-UX(@Charles Duffy)와 같은 POSIX 호환 유틸리티가 있습니다.

https://stackoverflow.com/a/1116890/45375,에 영감을 받은 다음 솔루션은 도우미 셸 기능을 정의하며, 이 기능은 POSIX-Link(NUIXX 호환 구현에 영향을 미치는 영향입니다.궁극적인 대상이 있어야 합니다.

주의: 이 기능은 기능이며 POSIX 호환 옵션을 가진 POSIX 유틸리티만 사용한다는 점에서 POSIX 호환입니다.POSIX 준거 셸 코드로 기술되어 있는 이 함수의 버전(용)/bin/sh참조해 주세요.

  • 한다면readlink사용할 수 있습니다. (옵션 없이) 사용됩니다.대부분의 최신 플랫폼에 해당됩니다.

  • 그 이외의 경우는, 로부터의 출력이 됩니다.ls -l는 해석됩니다.이것은 심볼링크 타깃을 판별하는 유일한 POSIX 준거 방법입니다.
    경고: 파일 이름 또는 경로에 리터럴 하위 문자열이 포함되어 있으면 중단됩니다.->- 하지만 그럴 가능성은 낮습니다.
    (플랫폼에 주의해 주세요.readlink@Charles Duffy는 HP-UX의 심볼링크를 해결하기 위한 다른 비 POSIX 방법을 제공할 수 있습니다.find를 지원하는 유틸리티%lchar.를 포맷합니다.-printf주요, 간결성을 위해 함수는 이러한 경우를 감지하려고 하지 않습니다.)

  • 설치 가능한 유틸리티(스크립트) 형식의 함수는 npm 레지스트리에서 찾을rreadlink 수 있습니다.Linux 및 macOS 에서는, 인스톨 합니다.[sudo] npm install -g rreadlink 있다; 있다;;;;;;bash)의 인스톨 순서에 따릅니다.

인수가 심볼 링크인 경우 최종 대상의 표준 경로가 반환되고, 그렇지 않은 경우 인수의 자체 표준 경로가 반환됩니다.

#!/usr/bin/env bash

# Helper function.
rreadlink() ( # execute function in a *subshell* to localize the effect of `cd`, ...

  local target=$1 fname targetDir readlinkexe=$(command -v readlink) CDPATH= 

  # Since we'll be using `command` below for a predictable execution
  # environment, we make sure that it has its original meaning.
  { \unalias command; \unset -f command; } &>/dev/null

  while :; do # Resolve potential symlinks until the ultimate target is found.
      [[ -L $target || -e $target ]] || { command printf '%s\n' "$FUNCNAME: ERROR: '$target' does not exist." >&2; return 1; }
      command cd "$(command dirname -- "$target")" # Change to target dir; necessary for correct resolution of target path.
      fname=$(command basename -- "$target") # Extract filename.
      [[ $fname == '/' ]] && fname='' # !! curiously, `basename /` returns '/'
      if [[ -L $fname ]]; then
        # Extract [next] target path, which is defined
        # relative to the symlink's own directory.
        if [[ -n $readlinkexe ]]; then # Use `readlink`.
          target=$("$readlinkexe" -- "$fname")
        else # `readlink` utility not available.
          # Parse `ls -l` output, which, unfortunately, is the only POSIX-compliant 
          # way to determine a symlink's target. Hypothetically, this can break with
          # filenames containig literal ' -> ' and embedded newlines.
          target=$(command ls -l -- "$fname")
          target=${target#* -> }
        fi
        continue # Resolve [next] symlink target.
      fi
      break # Ultimate target reached.
  done
  targetDir=$(command pwd -P) # Get canonical dir. path
  # Output the ultimate target's canonical path.
  # Note that we manually resolve paths ending in /. and /.. to make sure we
  # have a normalized path.
  if [[ $fname == '.' ]]; then
    command printf '%s\n' "${targetDir%/}"
  elif  [[ $fname == '..' ]]; then
    # Caveat: something like /var/.. will resolve to /private (assuming
    # /var@ -> /private/var), i.e. the '..' is applied AFTER canonicalization.
    command printf '%s\n' "$(command dirname -- "${targetDir}")"
  else
    command printf '%s\n' "${targetDir%/}/$fname"
  fi
)
                
# Determine ultimate script dir. using the helper function.
# Note that the helper function returns a canonical path.
scriptDir=$(dirname -- "$(rreadlink "$BASH_SOURCE")")

한 줄이면 돼요.

cat "`dirname $0`"/../some.txt

언급URL : https://stackoverflow.com/questions/24112727/relative-paths-based-on-file-location-instead-of-current-working-directory

반응형