[bash] $ 0와 BASH_SOURCE 중에서 선택

어떻게 하나를 선택할 않습니다 "$0""${BASH_SOURCE[0]}"

GNU 의이 설명 은 저에게별로 도움이되지 않았습니다.

    BASH_SOURCE

 An array variable whose members are the source filenames where the
 corresponding shell function names in the FUNCNAME array variable are
 defined. The shell function ${FUNCNAME[$i]} is defined in the file
 ${BASH_SOURCE[$i]} and called from ${BASH_SOURCE[$i+1]}



답변

참고 : POSIX 호환 솔루션의 경우이 답변을 참조하십시오 .

${BASH_SOURCE[0]}(또는 간단히 $BASH_SOURCE[1]
)에는 모든 호출 시나리오 에서 포함하는 스크립트의 (잠재적으로 상대적인) 경로가 포함되어 있습니다. 특히 스크립트가 소싱 된 경우에도 $0.

또한 Charles Duffy가 지적했듯이 호출자 $0임의의 값 으로 설정할 수 있습니다 .
반대로 이름이 지정된 파일이 없으면 비워 둘 $BASH_SOURCE 있습니다. 예 :
echo 'echo "[$BASH_SOURCE]"' | bash

다음 예는이를 설명합니다.

스크립트 foo:

#!/bin/bash
echo "[$0] vs. [${BASH_SOURCE[0]}]"

$ bash ./foo
[./foo] vs. [./foo]

$ ./foo
[./foo] vs. [./foo]

$ . ./foo
[bash] vs. [./foo]

$0BASH_SOURCE이름에서 알 수 있듯이 는 POSIX 셸 사양의 일부인 반면는 Bash 전용입니다.


[1] 선택 읽기 : ${BASH_SOURCE[0]}vs.$BASH_SOURCE :

배시는 기준 소자를 허용 0배열 하여 변수 표기 대신 기입 ${arr[0]}하면 쓸 수있다 $arr; 즉, 변수 가 스칼라것처럼 참조하면 index에있는 요소를 얻습니다 0.

이 기능을 사용 $arr하면 배열 이라는 사실이 모호해 지므로 인기있는 쉘 코드 linter shellcheck.net 에서 다음 경고를 발행합니다 (이 글을 쓰는 시점에서).

SC2128 : 인덱스없이 배열을 확장하면 첫 번째 요소 만 제공됩니다.

참고 :이 경고는 도움이되지만 더 정확할 수 있습니다. 첫 번째 요소를 반드시 얻을 필요는 없기 때문 입니다. 특히 0반환 되는 인덱스의 요소 이므로 첫 번째 요소에 더 높은 인덱스가있는 경우- Bash에서 가능합니다-당신은 빈 문자열을 얻게 될 것입니다; 시도해보십시오 'a[1]='hi'; echo "$a"'.
(반면에 zsh, 어느 배신자는 실제로 수행 색인에 관계없이 최초의 요소를 리턴).

실용적으로 말하면, 당신은 인해 무명이 기능을 피하다하도록 선택할 수 있습니다, 그러나 예상 작동하고, 당신은 거의 경우 이제까지 접근 필요와 indices없는 것 , 다른 것보다 0배열 변수의 ${BASH_SOURCE[@]}.


답변

이 스크립트는 설명하는 데 도움이 될 수 있습니다. 외부 스크립트는 내부 스크립트를 호출하는 중간 스크립트를 호출합니다.

$ cat outer.sh
#!/usr/bin/env bash
./middle.sh
$ cat middle.sh
#!/usr/bin/env bash
./inner.sh
$ cat inner.sh
#!/usr/bin/env bash
echo "\$0 = '$0'"
echo "\${BASH_SOURCE[0]} = '${BASH_SOURCE[0]}'"
echo "\${BASH_SOURCE[1]} = '${BASH_SOURCE[1]}'"
echo "\${BASH_SOURCE[2]} = '${BASH_SOURCE[2]}'"
$ ./outer.sh
$0 = './inner.sh'
$BASH_SOURCE[0] = './inner.sh'
$BASH_SOURCE[1] = ''
$BASH_SOURCE[2] = ''

그러나 스크립트 호출을 source문으로 변경하면 :

$ cat outer.sh
#!/usr/bin/env bash
source ./middle.sh
$ cat middle.sh
#!/usr/bin/env bash
source ./inner.sh
$ cat inner.sh
#!/usr/bin/env bash
echo "\$0 = '$0'"
echo "\${BASH_SOURCE[0]} = '${BASH_SOURCE[0]}'"
echo "\${BASH_SOURCE[1]} = '${BASH_SOURCE[1]}'"
echo "\${BASH_SOURCE[2]} = '${BASH_SOURCE[2]}'"
$ ./outer.sh
$0 = './outer.sh'
$BASH_SOURCE[0] = './inner.sh'
$BASH_SOURCE[1] = './middle.sh'
$BASH_SOURCE[2] = './outer.sh'


답변

이식성을 위해 ${BASH_SOURCE[0]}정의 된 경우 사용하고 $0그렇지 않은 경우 사용하십시오. 그것은 준다

${BASH_SOURCE[0]:-$0}

특히, zsh에서 스크립트가 sourced 인 경우에도 $ 0에는 올바른 파일 경로가 포함되어 있습니다 .


답변