1

I saw this shell script in Zookeeper zkClear.sh.

ZOOBIN="${BASH_SOURCE-$0}"

Can anyone tell me the meaning of this script? Thanks.

Braiam
  • 1
  • 11
  • 47
  • 78
Machi
  • 403
  • 2
  • 14
  • 1
    Why has this question been closed? This is a valid question which request the meaning and subtleties about this notation. – kvantour Feb 03 '21 at 13:02
  • 1
    What part you don't understand? The `${...}` or what `BASH_SOURCE` means? – Braiam Feb 03 '21 at 13:17
  • ... Or the parameter expansion, or the specific reason this particular use case uses this particular parameter expansion? – tripleee Feb 03 '21 at 13:19
  • BASH_SOURCE-$0 this confused me so much. Can I treat "BASH_SOURCE" here as a string? What does it mean when BASH_SOURCE "minus" $0? – Machi Feb 04 '21 at 03:27

3 Answers3

5

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:

  1. 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.

  2. 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.

kvantour
  • 25,269
  • 4
  • 47
  • 72
1

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.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111
0

${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/