가장 일반적인 경우 $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실제로 조회가 현재 디렉토리에서 발견 되지 않는 한 스크립트 경로를 포함 하지 않았습니다 .$PATHthe-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.
어쨌든 모든 셸에서 $0a를 포함하지 /않고 읽을 수 없는 것을 발견하면 에서 찾은 것 같습니다 $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 답변에 대한 의견을 이해하려고 노력하고 있습니다.