etc./StackOverFlow

스크립트 자체 내에서 Bash 스크립트의 소스 디렉토리를 어떻게 얻을 수 있습니까?

청렴결백한 만능 재주꾼 2021. 9. 22. 13:27
반응형

질문자 :Community Wiki


해당 스크립트 에서 Bash 스크립트가 있는 디렉토리의 경로를 어떻게 얻습니까?

Bash 스크립트를 다른 응용 프로그램의 실행기로 사용하고 싶습니다. 작업 디렉토리를 Bash 스크립트가 있는 디렉토리로 변경하고 싶습니다. 따라서 다음과 같이 해당 디렉토리의 파일에 대해 작업할 수 있습니다.

 $ ./application


답변자 : Community Wiki


#!/usr/bin/env bash SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"

스크립트가 호출되는 위치에 관계없이 스크립트의 전체 디렉토리 이름을 제공하는 유용한 한 줄짜리입니다.

스크립트를 찾는 데 사용된 경로의 마지막 구성 요소가 심볼릭 링크가 아닌 한 작동합니다(디렉토리 링크는 정상임). 스크립트 자체에 대한 링크도 해결하려면 여러 줄 솔루션이 필요합니다.

 #!/usr/bin/env bash SOURCE="${BASH_SOURCE[0]}" while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )" SOURCE="$(readlink "$SOURCE")" [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located done DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"

이 마지막 것은 aliases, source , bash -c , symlinks 등의 모든 조합에서 작동합니다.

주의: 이 스니펫을 실행하기 전에 다른 디렉토리로 cd

또한 $CDPATH gotchas 및 stderr 출력 부작용에 주의하십시오. 사용자가 cd를 스마트하게 재정의하여 출력을 대신 stderr로 리디렉션한 경우(Mac에서 update_terminal_cwd >&2 cd 명령 끝에 >/dev/null 2>&1 을 추가하면 두 가지 가능성이 모두 처리됩니다.

작동 방식을 이해하려면 다음과 같이 더 자세한 형식을 실행해 보세요.

 #!/usr/bin/env bash SOURCE="${BASH_SOURCE[0]}" while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink TARGET="$(readlink "$SOURCE")" if [[ $TARGET == /* ]]; then echo "SOURCE '$SOURCE' is an absolute symlink to '$TARGET'" SOURCE="$TARGET" else DIR="$( dirname "$SOURCE" )" echo "SOURCE '$SOURCE' is a relative symlink to '$TARGET' (relative to '$DIR')" SOURCE="$DIR/$TARGET" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located fi done echo "SOURCE is '$SOURCE'" RDIR="$( dirname "$SOURCE" )" DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )" if [ "$DIR" != "$RDIR" ]; then echo "DIR '$RDIR' resolves to '$DIR'" fi echo "DIR is '$DIR'"

그러면 다음과 같이 인쇄됩니다.

 SOURCE './scriptdir.sh' is a relative symlink to 'sym2/scriptdir.sh' (relative to '.') SOURCE is './sym2/scriptdir.sh' DIR './sym2' resolves to '/home/ubuntu/dotfiles/fo fo/real/real1/real2' DIR is '/home/ubuntu/dotfiles/fo fo/real/real1/real2'


답변자 : Community Wiki


dirname "$0" :

 #!/bin/bash echo "The script you are running has basename `basename "$0"`, dirname `dirname "$0"`" echo "The present working directory is `pwd`"

포함된 디렉토리에서 스크립트를 실행하지 않는 경우 pwd 만 사용하면 작동하지 않습니다.

 [matt@server1 ~]$ pwd /home/matt [matt@server1 ~]$ ./test2.sh The script you are running has basename test2.sh, dirname . The present working directory is /home/matt [matt@server1 ~]$ cd /tmp [matt@server1 tmp]$ ~/test2.sh The script you are running has basename test2.sh, dirname /home/matt The present working directory is /tmp


답변자 : Community Wiki


dirname $0 (스크립트 이름) 변수에서 파일 이름까지의 경로를 간단히 구문 분석하는 가장 기본적인 명령입니다.

 dirname "$0"

하지만 mat b가 지적한 것처럼 스크립트를 어떻게 호출하느냐에 따라 반환되는 경로가 달라진다. pwd 는 스크립트가 있는 디렉토리가 아니라 현재 디렉토리만 알려 주기 때문에 작업을 수행하지 않습니다. 또한 스크립트에 대한 심볼릭 링크가 실행되면 (아마도 상대) 경로를 얻게 됩니다. 실제 스크립트가 아닌 링크가 있는 위치로 이동합니다.

다른 사람들은 readlink 명령을 언급했지만 가장 간단하게 다음을 사용할 수 있습니다.

 dirname "$(readlink -f "$0")"

readlink 는 스크립트 경로를 파일 시스템의 루트에서 절대 경로로 해석합니다. 따라서 단일 또는 이중 점, 물결표 및/또는 기호 링크가 포함된 모든 경로는 전체 경로로 확인됩니다.

다음은 각각 whatdir.sh 보여주는 스크립트입니다.

 #!/bin/bash echo "pwd: `pwd`" echo "\$0: $0" echo "basename: `basename $0`" echo "dirname: `dirname $0`" echo "dirname/readlink: $(dirname $(readlink -f $0))"

상대 경로를 사용하여 내 홈 디렉토리에서 이 스크립트를 실행합니다.

 >>>$ ./whatdir.sh pwd: /Users/phatblat $0: ./whatdir.sh basename: whatdir.sh dirname: . dirname/readlink: /Users/phatblat

다시 말하지만 스크립트의 전체 경로를 사용합니다.

 >>>$ /Users/phatblat/whatdir.sh pwd: /Users/phatblat $0: /Users/phatblat/whatdir.sh basename: whatdir.sh dirname: /Users/phatblat dirname/readlink: /Users/phatblat

이제 디렉토리 변경:

 >>>$ cd /tmp >>>$ ~/whatdir.sh pwd: /tmp $0: /Users/phatblat/whatdir.sh basename: whatdir.sh dirname: /Users/phatblat dirname/readlink: /Users/phatblat

마지막으로 심볼릭 링크를 사용하여 스크립트를 실행합니다.

 >>>$ ln -s ~/whatdir.sh whatdirlink.sh >>>$ ./whatdirlink.sh pwd: /tmp $0: ./whatdirlink.sh basename: whatdirlink.sh dirname: . dirname/readlink: /Users/phatblat


답변자 : Community Wiki


pushd . > /dev/null SCRIPT_PATH="${BASH_SOURCE[0]}" if ([ -h "${SCRIPT_PATH}" ]); then while([ -h "${SCRIPT_PATH}" ]); do cd `dirname "$SCRIPT_PATH"`; SCRIPT_PATH=`readlink "${SCRIPT_PATH}"`; done fi cd `dirname ${SCRIPT_PATH}` > /dev/null SCRIPT_PATH=`pwd`; popd > /dev/null

다음을 포함한 모든 버전에서 작동합니다.

  • 다중 깊이 소프트 링크를 통해 호출될 때
  • 파일을 만들 때
  • source " 명령에 의해 호출될 때 . (점) 연산자.
  • $0 이 호출자로부터 수정될 때.
  • "./script"
  • "/full/path/to/script"
  • "/some/path/../../another/path/script"
  • "./some/folder/script"

또는 Bash 스크립트 자체가 상대 심볼릭 링크인 경우 이를 따르고 연결된 스크립트의 전체 경로를 반환 하려고 합니다.

 pushd . > /dev/null SCRIPT_PATH="${BASH_SOURCE[0]}"; if ([ -h "${SCRIPT_PATH}" ]) then while([ -h "${SCRIPT_PATH}" ]) do cd `dirname "$SCRIPT_PATH"`; SCRIPT_PATH=`readlink "${SCRIPT_PATH}"`; done fi cd `dirname ${SCRIPT_PATH}` > /dev/null SCRIPT_PATH=`pwd`; popd > /dev/null

SCRIPT_PATH 는 호출 방식에 관계없이 전체 경로로 제공됩니다.

스크립트 시작 부분에서 이것을 찾으십시오.



답변자 : Community Wiki


짧은 답변:

 `dirname $0`

또는 ( 바람직하게는 ):

 $(dirname "$0")


답변자 : Community Wiki


$BASH_SOURCE 를 사용할 수 있습니다.

 #!/bin/bash scriptdir=`dirname "$BASH_SOURCE"`

Bash 확장이므로 #!/bin/sh 아니라 #!/bin/bash 를 사용해야 합니다.



답변자 : Community Wiki


다음은 기억하기 쉬운 스크립트입니다.

 DIR="$(dirname "${BASH_SOURCE[0]}")" # Get the directory name DIR="$(realpath "${DIR}")" # Resolve its full path if need be


답변자 : Community Wiki


이렇게 해야 합니다.

 DIR="$(dirname "$(readlink -f "$0")")"

이것은 경로의 심볼릭 링크 및 공백과 함께 작동합니다.

dirnamereadlink 매뉴얼 페이지를 참조하십시오.

댓글 트랙에서 Mac OS에서는 작동하지 않는 것 같습니다. 왜 그런지 모르겠습니다. 어떤 제안?



답변자 : Community Wiki


pwd 는 현재 작업 디렉토리를 찾는 데 사용할 수 있고 dirname 은 특정 파일의 디렉토리를 찾는 $0 이므로 dirname $0 은 현재 스크립트의 디렉토리를 제공해야 함).

그러나 dirname 은 파일 이름의 디렉토리 부분을 정확하게 제공하며 현재 작업 디렉토리에 상대적일 가능성이 높습니다. 어떤 이유로 스크립트가 디렉토리를 변경해야 하는 경우 dirname 의 출력은 의미가 없습니다.

다음을 제안합니다.

 #!/bin/bash reldir=`dirname $0` cd $reldir directory=`pwd` echo "Directory is $directory"

이런 식으로 상대 디렉토리가 아닌 절대 디렉토리를 얻습니다.

스크립트는 별도의 Bash 인스턴스에서 실행되므로 나중에 작업 디렉터리를 복원할 필요가 없지만 어떤 이유로 스크립트에서 다시 변경하려는 경우 pwd 값을 쉽게 할당할 수 있습니다. 나중에 사용할 수 있도록 디렉토리를 변경하기 전에 변수.

비록

 cd `dirname $0`

질문의 특정 시나리오를 해결하면 절대 경로가 더 일반적으로 더 유용하다는 것을 알았습니다.



답변자 : Community Wiki


나는 이것이 다른 사람들이 해낸 것처럼 쉽지 않다고 생각합니다. 현재 디렉토리가 반드시 스크립트가 있는 디렉토리가 아니므로 pwd $0 에도 항상 정보가 있는 것은 아닙니다. 스크립트를 호출하는 다음 세 가지 방법을 고려하십시오.

 ./script /usr/bin/script script

첫 번째 및 세 번째 방법에서 $0 에는 전체 경로 정보가 없습니다. 두 번째와 세 번째에서는 pwd 가 작동하지 않습니다. 세 번째 방법으로 디렉토리를 얻는 유일한 방법은 경로를 통해 실행하고 올바른 일치가 있는 파일을 찾는 것입니다. 기본적으로 코드는 OS가 하는 일을 다시 실행해야 합니다.

요청한 작업을 수행하는 한 가지 방법은 /usr/share 디렉토리의 데이터를 하드코딩하고 전체 경로로 참조하는 것입니다. 어쨌든 데이터는 /usr/bin 디렉토리에 있어서는 안 되므로 이것이 아마도 해야 할 일입니다.



답변자 : Community Wiki


SCRIPT_DIR=$( cd ${0%/*} && pwd -P )


답변자 : Community Wiki


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


답변자 : Community Wiki


이것은 Mac OS X v10.6.6 (Snow Leopard)에서 현재 작업 디렉토리를 가져옵니다.

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


답변자 : Community Wiki


이것은 Linux에만 해당되지만 다음을 사용할 수 있습니다.

 SELF=$(readlink /proc/$$/fd/255)


답변자 : Community Wiki


다음은 POSIX 호환 원 라이너입니다.

 SCRIPT_PATH=`dirname "$0"`; SCRIPT_PATH=`eval "cd \"$SCRIPT_PATH\" && pwd"` # test echo $SCRIPT_PATH


답변자 : Community Wiki


이를 수행하는 가장 짧고 우아한 방법은 다음과 같습니다.

 #!/bin/bash DIRECTORY=$(cd `dirname $0` && pwd) echo $DIRECTORY

이것은 모든 플랫폼에서 작동하며 매우 깨끗합니다.

자세한 내용은 " 해당 bash 스크립트가 있는 디렉토리는 무엇입니까? "에서 찾을 수 있습니다.



답변자 : Community Wiki


#!/bin/sh PRG="$0" # need this for relative symlinks while [ -h "$PRG" ] ; do PRG=`readlink "$PRG"` done scriptdir=`dirname "$PRG"`


답변자 : Community Wiki


다음은 간단하고 올바른 방법입니다.

 actual_path=$(readlink -f "${BASH_SOURCE[0]}") script_dir=$(dirname "$actual_path")

설명:

  • ${BASH_SOURCE[0]} - 스크립트의 전체 경로입니다. 이 값은 스크립트가 소싱되는 경우에도 정확합니다. 예를 들어 source <(echo 'echo $0')bash 를 인쇄하지만 ${BASH_SOURCE[0]} 스크립트의 전체 경로가 인쇄됩니다. (물론 이것은 Bash에 의존하는 것이 괜찮다고 가정합니다.)

  • readlink -f - 지정된 경로의 모든 심볼릭 링크를 재귀적으로 확인합니다. 이것은 GNU 확장이며 (예를 들어) BSD 시스템에서는 사용할 수 없습니다. Mac을 실행하는 경우 Homebrew를 사용하여 GNU coreutils 를 설치하고 이를 greadlink -f 대체할 수 있습니다.

  • 물론 dirname 은 경로의 상위 디렉토리를 가져옵니다.



답변자 : Community Wiki


나는 이것들을 모두 시도했지만 아무도 효과가 없었습니다. 하나는 매우 가까웠지만 작은 벌레가 있어 심하게 부러졌습니다. 그들은 경로를 따옴표로 묶는 것을 잊었습니다.

또한 많은 사람들은 쉘에서 스크립트를 실행한다고 가정하므로 새 스크립트를 열 때 기본적으로 집으로 설정된다는 사실을 잊어버립니다.

크기에 대해 이 디렉토리를 사용해 보십시오.

 /var/No one/Thought/About Spaces Being/In a Directory/Name/And Here's your file.text

실행 방법이나 위치에 관계없이 올바르게 수행됩니다.

 #!/bin/bash echo "pwd: `pwd`" echo "\$0: $0" echo "basename: `basename "$0"`" echo "dirname: `dirname "$0"`"

따라서 실제로 유용하게 만들기 위해 실행 중인 스크립트의 디렉토리로 변경하는 방법은 다음과 같습니다.

 cd "`dirname "$0"`"


답변자 : Community Wiki


이것은 e-satis 및 3bcdnlklvc04a가 답변 에서 지적한 솔루션에 대한 약간의 개정판입니다.

 SCRIPT_DIR='' pushd "$(dirname "$(readlink -f "$BASH_SOURCE")")" > /dev/null && { SCRIPT_DIR="$PWD" popd > /dev/null }

나열된 모든 경우에 여전히 작동해야 합니다.

이것은 실패한 pushd popd 를 방지합니다. konsolebox 덕분에.



답변자 : Community Wiki


나는 다음과 같은 것을 사용할 것입니다 :

 # Retrieve the full pathname of the called script scriptPath=$(which $0) # Check whether the path is a link or not if [ -L $scriptPath ]; then # It is a link then retrieve the target path and get the directory name sourceDir=$(dirname $(readlink -f $scriptPath)) else # Otherwise just get the directory name of the script path sourceDir=$(dirname $scriptPath) fi


답변자 : Community Wiki


GNU coreutils readlink 시스템(예: Linux):

 $(readlink -f "$(dirname "$0")")

$0 에 스크립트 파일 이름이 포함되어 있으면 BASH_SOURCE 를 사용할 필요가 없습니다.



답변자 : Community Wiki


$_ $0 의 대안으로 언급할 가치가 있습니다. Bash에서 스크립트를 실행하는 경우 허용되는 답변을 다음과 같이 줄일 수 있습니다.

 DIR="$( dirname "$_" )"

이것은 스크립트의 첫 번째 명령문이어야 합니다.



답변자 : Community Wiki


다음은 스크립트 정보를 얻는 짧은 방법입니다.

폴더 및 파일:

 Script: "/tmp/src dir/test.sh" Calling folder: "/tmp/src dir/other"

다음 명령 사용:

 echo Script-Dir : `dirname "$(realpath $0)"` echo Script-Dir : $( cd ${0%/*} && pwd -P ) echo Script-Dir : $(dirname "$(readlink -f "$0")") echo echo Script-Name : `basename "$(realpath $0)"` echo Script-Name : `basename $0` echo echo Script-Dir-Relative : `dirname "$BASH_SOURCE"` echo Script-Dir-Relative : `dirname $0` echo echo Calling-Dir : `pwd`

그리고 나는이 출력을 얻었다 :

 Script-Dir : /tmp/src dir Script-Dir : /tmp/src dir Script-Dir : /tmp/src dir Script-Name : test.sh Script-Name : test.sh Script-Dir-Relative : .. Script-Dir-Relative : .. Calling-Dir : /tmp/src dir/other

또한 참조: https://pastebin.com/J8KjxrPF



답변자 : Community Wiki


이것은 Bash 3.2에서 작동합니다.

 path="$( dirname "$( which "$0" )" )"

$PATH~/bin 디렉토리가 있다면 이 디렉토리 안에 A 가 A ~/bin/lib/B 스크립트의 소스입니다. lib 서브디렉토리에서 원본 스크립트에 상대적인 위치는 알지만 사용자의 현재 디렉토리에 상대적인 위치는 알 수 없습니다.

이것은 다음으로 해결됩니다( A 내부).

 source "$( dirname "$( which "$0" )" )/lib/B"

사용자가 어디에 있는지 또는 스크립트를 호출하는 방법은 중요하지 않습니다. 이것은 항상 작동합니다.



답변자 : Community Wiki


다음을 사용해보십시오.

 real=$(realpath "$(dirname "$0")")


답변자 : Community Wiki


나는 주어진 많은 답변을 비교했고 더 간결한 솔루션을 생각해 냈습니다. 이것들은 좋아하는 조합에서 발생하는 모든 미친 극단적 인 경우를 처리하는 것 같습니다.

  • 절대 경로 또는 상대 경로
  • 파일 및 디렉토리 소프트 링크
  • script , bash script , bash -c script , source script 또는 . script
  • 디렉토리 및/또는 파일 이름의 공백, 탭, 줄 바꿈, 유니코드 등
  • 하이픈으로 시작하는 파일 이름

Linux에서 실행 중인 경우 proc 핸들을 사용하여 현재 실행 중인 스크립트의 완전히 확인된 소스를 찾는 것이 가장 좋은 솔루션인 /dev/pts/X ).

 resolved="$(readlink /proc/$$/fd/255 && echo X)" && resolved="${resolved%$'\nX'}"

이것은 약간 추악한 부분이 있지만 수정 사항은 간결하고 이해하기 쉽습니다. 우리는 bash 프리미티브만 사용하지 않지만 readlink 가 작업을 상당히 단순화하기 때문에 괜찮습니다. echo XX 를 추가하여 파일 이름의 후행 공백이 사용되지 않도록 하고 줄 끝에 ${VAR%X} X 제거합니다. readlink 는 자체 줄 바꿈을 추가하기 때문에(이전의 속임수가 아니라면 일반적으로 명령 대체에서 먹힐 것입니다), 우리도 제거해야 합니다. \n 과 같은 이스케이프 시퀀스를 사용하여 줄 바꿈을 나타낼 $'' 인용 체계를 사용하여 가장 쉽게 수행할 수 있습니다.

위의 내용은 Linux에서 현재 실행 중인 스크립트를 찾는 데 필요한 사항을 다루고 있지만 proc 파일 시스템이 없거나 다른 파일의 완전히 확인된 경로를 찾으려고 한다면 아마도 ' 아래 코드가 도움이 될 것입니다. 위의 한 줄에서 약간만 수정한 것입니다. 이상한 디렉토리/파일 이름을 가지고 놀고 있다면 lsreadlink 를 모두 사용하여 출력을 확인하는 것이 유익합니다. ls 는 "단순화된" 경로를 출력하고 ? 개행과 같은 것.

 absolute_path=$(readlink -e -- "${BASH_SOURCE[0]}" && echo x) && absolute_path=${absolute_path%?x} dir=$(dirname -- "$absolute_path" && echo x) && dir=${dir%?x} file=$(basename -- "$absolute_path" && echo x) && file=${file%?x} ls -l -- "$dir/$file" printf '$absolute_path: "%s"\n' "$absolute_path"


답변자 : Community Wiki


나는 이것을 가지고 있다고 믿습니다. 나는 파티에 늦었지만 일부 사람들은 이 스레드를 알게 된다면 여기에 있는 것에 감사할 것이라고 생각합니다. 주석은 다음을 설명해야 합니다.

 #!/bin/sh # dash bash ksh # !zsh (issues). G. Nixon, 12/2013. Public domain. ## 'linkread' or 'fullpath' or (you choose) is a little tool to recursively ## dereference symbolic links (ala 'readlink') until the originating file ## is found. This is effectively the same function provided in stdlib.h as ## 'realpath' and on the command line in GNU 'readlink -f'. ## Neither of these tools, however, are particularly accessible on the many ## systems that do not have the GNU implementation of readlink, nor ship ## with a system compiler (not to mention the requisite knowledge of C). ## This script is written with portability and (to the extent possible, speed) ## in mind, hence the use of printf for echo and case statements where they ## can be substituded for test, though I've had to scale back a bit on that. ## It is (to the best of my knowledge) written in standard POSIX shell, and ## has been tested with bash-as-bin-sh, dash, and ksh93. zsh seems to have ## issues with it, though I'm not sure why; so probably best to avoid for now. ## Particularly useful (in fact, the reason I wrote this) is the fact that ## it can be used within a shell script to find the path of the script itself. ## (I am sure the shell knows this already; but most likely for the sake of ## security it is not made readily available. The implementation of "$0" ## specificies that the $0 must be the location of **last** symbolic link in ## a chain, or wherever it resides in the path.) This can be used for some ## ...interesting things, like self-duplicating and self-modifiying scripts. ## Currently supported are three errors: whether the file specified exists ## (ala ENOENT), whether its target exists/is accessible; and the special ## case of when a sybolic link references itself "foo -> foo": a common error ## for beginners, since 'ln' does not produce an error if the order of link ## and target are reversed on the command line. (See POSIX signal ELOOP.) ## It would probably be rather simple to write to use this as a basis for ## a pure shell implementation of the 'symlinks' util included with Linux. ## As an aside, the amount of code below **completely** belies the amount ## effort it took to get this right -- but I guess that's coding for you. ##===-------------------------------------------------------------------===## for argv; do :; done # Last parameter on command line, for options parsing. ## Error messages. Use functions so that we can sub in when the error occurs. recurses(){ printf "Self-referential:\n\t$argv ->\n\t$argv\n" ;} dangling(){ printf "Broken symlink:\n\t$argv ->\n\t"$(readlink "$argv")"\n" ;} errnoent(){ printf "No such file: "$@"\n" ;} # Borrow a horrible signal name. # Probably best not to install as 'pathfull', if you can avoid it. pathfull(){ cd "$(dirname "$@")"; link="$(readlink "$(basename "$@")")" ## 'test and 'ls' report different status for bad symlinks, so we use this. if [ ! -e "$@" ]; then if $(ls -d "$@" 2>/dev/null) 2>/dev/null; then errnoent 1>&2; exit 1; elif [ ! -e "$@" -a "$link" = "$@" ]; then recurses 1>&2; exit 1; elif [ ! -e "$@" ] && [ ! -z "$link" ]; then dangling 1>&2; exit 1; fi fi ## Not a link, but there might be one in the path, so 'cd' and 'pwd'. if [ -z "$link" ]; then if [ "$(dirname "$@" | cut -c1)" = '/' ]; then printf "$@\n"; exit 0; else printf "$(pwd)/$(basename "$@")\n"; fi; exit 0 fi ## Walk the symlinks back to the origin. Calls itself recursivly as needed. while [ "$link" ]; do cd "$(dirname "$link")"; newlink="$(readlink "$(basename "$link")")" case "$newlink" in "$link") dangling 1>&2 && exit 1 ;; '') printf "$(pwd)/$(basename "$link")\n"; exit 0 ;; *) link="$newlink" && pathfull "$link" ;; esac done printf "$(pwd)/$(basename "$newlink")\n" } ## Demo. Install somewhere deep in the filesystem, then symlink somewhere ## else, symlink again (maybe with a different name) elsewhere, and link ## back into the directory you started in (or something.) The absolute path ## of the script will always be reported in the usage, along with "$0". if [ -z "$argv" ]; then scriptname="$(pathfull "$0")" # Yay ANSI l33t codes! Fancy. printf "\n\033[3mfrom/as: \033[4m$0\033[0m\n\n\033[1mUSAGE:\033[0m " printf "\033[4m$scriptname\033[24m [ link | file | dir ]\n\n " printf "Recursive readlink for the authoritative file, symlink after " printf "symlink.\n\n\n \033[4m$scriptname\033[24m\n\n " printf " From within an invocation of a script, locate the script's " printf "own file\n (no matter where it has been linked or " printf "from where it is being called).\n\n" else pathfull "$@" fi


답변자 : Gabriel Staples


실행 중인 스크립트 의 전체 파일 경로 , 전체 디렉토리기본 파일 이름 을 얻는 방법

대부분의 경우 방금 호출한 스크립트의 전체 경로만 확보하면 됩니다. realpath 사용하여 쉽게 달성할 수 있습니다. realpath 는 GNU coreutils의 일부입니다. 아직 설치하지 않은 경우(Ubuntu에서는 기본적으로 제공됨) sudo apt update && sudo apt install coreutils 있습니다.

get_script_path.sh :

 #!/bin/bash FULL_PATH_TO_SCRIPT="$(realpath "$0")" # You can then also get the full path to the directory, and the base # filename, like this: SCRIPT_DIRECTORY="$(dirname "$FULL_PATH_TO_SCRIPT")" SCRIPT_FILENAME="$(basename "$FULL_PATH_TO_SCRIPT")" # Now print it all out echo "FULL_PATH_TO_SCRIPT = \"$FULL_PATH_TO_SCRIPT\"" echo "SCRIPT_DIRECTORY = \"$SCRIPT_DIRECTORY\"" echo "SCRIPT_FILENAME = \"$SCRIPT_FILENAME\""

출력 예:

 ~/GS/dev/eRCaGuy_hello_world/bash$ ./get_script_path.sh FULL_PATH_TO_SCRIPT = "/home/gabriel/GS/dev/eRCaGuy_hello_world/bash/get_script_path.sh" SCRIPT_DIRECTORY = "/home/gabriel/GS/dev/eRCaGuy_hello_world/bash" SCRIPT_FILENAME = "get_script_path.sh"

realpath 는 또한 심볼릭 링크를 가리키기보다 타겟을 결정하고 가리키기 위해 심볼릭 링크를 성공적으로 따라갑니다.

위의 코드는 이제 bash/get_script_path.sh 파일에 있는 eRCaGuy_hello_world 저장소의 일부입니다.

참조:

  1. 상대가 주어진 절대 경로를 검색하는 방법


답변자 : Community Wiki


다음 교차 호환 솔루션을 사용해 보세요.

 CWD="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"

realpath 또는 readlink 와 같은 명령을 사용하지 못할 수 있기 때문입니다(운영 체제에 따라 다름).

$0 대신 ${BASH_SOURCE[0]} 를 사용하는 것이 좋습니다 source / . )을 소싱할 때 경로가 깨질 수 있습니다.

또는 Bash에서 다음 기능을 시도할 수 있습니다.

 realpath () { [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" }

이 함수는 하나의 인수를 취합니다. 인수에 이미 절대 경로가 있으면 그대로 인쇄하고, 그렇지 않으면 $PWD 변수 + 파일 이름 인수( ./ 접두사 제외)를 인쇄합니다.

관련된:



출처 : Here


출처 : http:www.stackoverflow.com/questions/59895/how-can-i-get-the-source-directory-of-a-bash-script-from-within-the-script-itsel">

반응형