가장 일반적인 경우 $0
스크립트에 대한 절대 또는 상대 경로를 포함하므로
script_path=$(readlink -e -- "$0")
( readlink
명령이 있고 지원 한다고 가정 -e
)은 일반적으로 스크립트에 대한 표준 절대 경로를 얻는 데 충분한 방법입니다.
$0
는 인터프리터에 전달 된 스크립트를 지정하는 인수에서 지정됩니다.
예를 들면 다음과 같습니다.
the-shell -shell-options the/script its args
$0
을 얻습니다 the/script
.
실행할 때 :
the/script its args
당신의 쉘은 :
exec("the/script", ["the/script", "its", "args"])
#! /bin/sh -
예를 들어 스크립트에 she-bang이 포함 된 경우 시스템은이를 다음과 같이 변환합니다.
exec("/bin/sh", ["/bin/sh" or "the/script", "-", "the/script", "its", "args"])
(she-bang을 포함하지 않거나 시스템이 ENOEXEC 오류를 반환하면 더 일반적으로 쉘이 동일한 작업을 수행합니다)
일부 시스템에서는 setuid / setgid 스크립트에 예외가 있습니다. 여기서 시스템은 일부 스크립트를 열고 fd
x
대신 실행합니다.
exec("/bin/sh", ["/bin/sh" or "the/script", "-", "/dev/fd/x", "its", "args"])
경쟁 조건을 피하기 위해 (이 경우 $0
포함 /dev/fd/x
).
지금, 당신은 그 주장 할 수 /dev/fd/x
있다 해당 스크립트의 경로. 그러나에서 읽는 경우 $0
입력을 사용할 때 스크립트가 중단됩니다.
호출 된 스크립트 명령 이름에 슬래시가 포함되어 있지 않으면 차이가 있습니다. 에:
the-script its args
당신의 쉘은에서 찾을 것 the-script
입니다 $PATH
. $PATH
일부 디렉토리에 대한 절대 또는 상대 경로 (빈 문자열 포함)를 포함 할 수 있습니다. 예를 들어, 현재 디렉토리에 $PATH
포함되어 /bin:/usr/bin:
있고 the-script
발견되면 쉘은 다음을 수행합니다.
exec("the-script", ["the-script", "its", "args"])
이것은 될 것입니다 :
exec("/bin/sh", ["/bin/sh" or "the-script", "-", "the-script", "its", "args"]
또는 다음에있는 경우 /usr/bin
:
exec("/usr/bin/the-script", ["the-script", "its", "args"])
exec("/bin/sh", ["/bin/sh" or "the-script" or "/usr/bin/the-script",
"-", "/usr/bin/the-script", "its", "args")
setuid corner case를 제외한 위의 모든 경우 $0
스크립트에 대한 경로 (절대 또는 상대)가 포함됩니다.
이제 스크립트를 다음과 같이 호출 할 수도 있습니다.
the-interpreter the-script its args
때 the-script
위와 같이 슬래시 문자를 포함하지 않는, 동작은 쉘에서 쉘에 약간 다릅니다.
오래된 AT & T ksh
구현은 실제로 스크립트를 무조건적으로 찾고 $PATH
있었으며 (실제로는 setuid 스크립트의 버그 및 보안 구멍이었습니다) $0
실제로 조회가 현재 디렉토리에서 발견 되지 않는 한 스크립트 경로를 포함 하지 않았습니다 .$PATH
the-script
최신 AT & T ksh
는 the-script
읽을 수있는 경우 현재 디렉토리에서 해석하려고 시도 합니다. 그렇지 않다면 그것은 읽을 수에 대한 조회 할 및 실행 the-script
에서 $PATH
.
들어 bash
경우 수표, the-script
현재 디렉토리에 (그리고 깨진 심볼릭 링크되지 않았 음)으로하지 않을 경우, 조회 (반드시 실행) 읽을위한 the-script
에서 $PATH
.
zsh
에 sh
에뮬레이션과 같이 할 것입니다 bash
경우 점을 제외하고 the-script
현재 디렉토리에 깨진 심볼릭 링크, 그것은 검색하지 않을 the-script
에 $PATH
대신 오류를보고합니다.
다른 모든 본쉘이 보이지 않는 the-script
에서 $PATH
.
어쨌든 모든 셸에서 $0
a를 포함하지 /
않고 읽을 수 없는 것을 발견하면 에서 찾은 것 같습니다 $PATH
. 그런 다음 파일의 $PATH
실행 파일 이 될 가능성이 높기 command -v -- "$0"
때문에 경로를 찾는 데 사용하는 안전한 근사치 일 수 있습니다 (그러나 $0
쉘 내장 또는 키워드 이름 (대부분의 쉘에서) 일 경우 작동하지 않습니다 ).
따라서 실제로 해당 사례를 다루고 싶다면 다음과 같이 작성할 수 있습니다.
progname=$0
[ -r "$progname" ] || progname=$(
IFS=:; set -f
for i in ${PATH-$(getconf PATH)}""; do
case $i in
"") p=$progname;;
*/) p=$i$progname;;
*) p=$i/$progname
esac
[ -r "$p" ] && exec printf '%s\n' "$p"
done
exit 1
) && progname=$(readlink -e -- "$progname") ||
progname=unknown
( ""
첨부 자는 separator 대신 분리 문자$PATH
로 $IFS
작동 하는 쉘이있는 후행 빈 요소를 보존하는 것입니다 ).
이제 스크립트를 호출하는 더 난해한 방법이 있습니다. 하나는 할 수 있습니다 :
the-shell < the-script
또는:
cat the-script | the-shell
이 경우 인터프리터가 수신 $0
한 첫 번째 인수 ( argv[0]
)가 되지만 (일반적으로 기본 이름이나 해당 인터프리터에 대한 경로 일 수 있습니다).the-shell
의 가치를 기반으로 상황에 처한 것을 감지하는 $0
것은 신뢰할 수 없습니다. ps -o args= -p "$$"
단서를 얻기 위해 출력을 볼 수 있습니다. 파이프의 경우 스크립트 경로로 돌아갈 수있는 실제 방법은 없습니다.
하나는 또한 할 수 있습니다 :
the-shell -c '. the-script' blah blih
그런 다음, 제외 zsh
(과 Bourne 쉘의 오래된 구현) $0
이 될 것입니다 blah
. 다시 한 번, 해당 쉘에서 스크립트 경로에 도달하기가 어렵습니다.
또는:
the-shell -c "$(cat the-script)" blah blih
기타
올바른 권한을 갖기 위해 $progname
다음과 같이 특정 문자열을 검색 할 수 있습니다.
progname=$0
[ -r "$progname" ] || progname=$(
IFS=:; set -f
for i in ${PATH-$(getconf PATH)}:; do
case $i in
"") p=$progname;;
*/) p=$i$progname;;
*) p=$i/$progname
esac
[ -r "$p" ] && exec printf '%s\n' "$p"
done
exit 1
) && progname=$(readlink -e -- "$progname") ||
progname=unknown
[ -f "$progname" ] && grep -q 7YQLVVD3UIUDTA32LSE8U9UOHH < "$progname" ||
progname=unknown
그러나 다시 한 번 노력할 가치가 있다고 생각하지 않습니다.
$0
대본 이외의 다른 상황에 대해 대답했으며 질문 제목에 대답합니다. 그러나$0
스크립트 자체가 있지만 디렉토리를 포함하지 않는 상황에도 관심이 있습니다 . 특히, 나는 SO 답변에 대한 의견을 이해하려고 노력하고 있습니다.