I saw this shell script in Zookeeper zkClear.sh
.
ZOOBIN="${BASH_SOURCE-$0}"
Can anyone tell me the meaning of this script? Thanks.
I saw this shell script in Zookeeper zkClear.sh
.
ZOOBIN="${BASH_SOURCE-$0}"
Can anyone tell me the meaning of this script? Thanks.
This is a very subtle. While there is no significant difference between ${BASH_SOURCE-$0}
and $BASH_SOURCE
in bash, it becomes practical when sourcing bash files in zsh.
There are two aspects here:
The meaning of the array BASH_SOURCE
and it's relation to $0
: This is well explained in choosing between $0 and BASH_SOURCE. However, the value of BASH_SOURCE
is only defined within the context of bash. Other shells have no knowledge of this array.
The parameter expansion ${var-string}
: when browsing the man pages of bash
or any POSIX related shell such as sh, ksh and even zsh, you can find that ${var-string}
resolves in string
if the variable var
does not exist.
So imagine now the following scripts:
$ cat src.bash
#!/usr/bin/env bash
echo "$0, ${BASH_SOURCE}, ${BASH_SOURCE-$0}"
$ cat exe.bash
#!/usr/bin/env bash
source ./src.bash
$ cat exe.zsh
#!/usr/bin/env zsh
source ./src.bash
When you execute these scripts in bash directly, you get the following results:
$ echo "$0, ${BASH_SOURCE}, ${BASH_SOURCE-$0}"
bash, , bash
$ source src.bash
bash, src.bash, src.bash
$ ./exe.bash
./exe.bash, ./src.bash, ./src.bash
This clearly shows that there is no significant difference between $BASH_SOURCE
and ${BASH_SOURCE-$0}
. Only when executed directly from the bash terminal as BASH_SOURCE
does not exist and is accordingly replaced.
From zsh, the story is different.
$ echo "$0, ${BASH_SOURCE}, ${BASH_SOURCE-$0}"
-zsh, , -zsh
$ source src.bash
src.bash, , src.bash
$ ./exe.zsh
./src.bash, , ./src.bash
Even though zsh has no knowledge of the variable BASH_SOURCE
, it also slightly changes the behaviour of $0
. For bash, $0
is always the name of the current executed script while in zsh it is the name of the current executed or sourced script. In the above, you clearly see the difference between $BASH_SOURCE
and ${BASH_SOURCE-$0}
. The latter always returns the value of the current executed or sourced file.
In conclusion, one could say that ${BASH_SOURCE-$0}
is a simple hack to get the path of the sourced file, independently of the shell the script is sourced from (zsh vs bash). Whether this is used for this reason in the original script is not certain, however it is likely that the author of the script had something like this in mind or is used to write source files that can be used both in zsh and bash.
From bash parameter expansion:
[...] Omitting the colon results in a test only for a parameter that is unset. Put another way, if the colon is included, the operator tests for both parameter’s existence and that its value is not null; if the colon is omitted, the operator tests only for existence.
${parameter:-word}
If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted.
So:
ZOOBIN="${BASH_SOURCE-$0}"
So we have:
BASH_SOURCE | ZOOBIN= |
---|---|
unset | $0 |
set, not empty | $BASH_SOURCE |
null (set&empty) | $BASH_SOURCE, which is null, so ZOOBIN will also be null |
null
means "set and empty", like var=''
or just var=
.
Prefer to use :-
so that if variable is empty, then use alternative word. As I doubt BASH_SOURCE
will ever be set but empty, if it's set it's going to have some path, this code is just fine.
And BASH_SOURCE
is explained in bash variables.
The meaning of ${BASH_SOURCE-$0}?
The meaning strongly depends on context. The meaning could be that if the file is sourced or running with bash
, then prefer to use BASH_SOURCE
variable. But if it is not sourced and not running under bash, ex running in ash
, then use $0
. The name ZOOBIN
suggest some path to binary and ZOO
is probably some application prefix.
${BASH_SOURCE[0]} contains the path of the containing script in all invocation scenarios. So when you source this variable, you'll get the path of the bash script.
So, in your case you print out the first element you retrieve when you call it from the environment as ${BASH_SOURCE}, which prints out "bash"(in my environment)
Read more here in this answer: https://stackoverflow.com/a/35006505/12592220
This link also explains it detail:https://www.systutorials.com/how-to-get-bash-scripts-own-path/