TL;DR I'd recommend using ${BASH_SOURCE:-$0}
as the most universal variant.
Previous answers are good but they do not mention one caveat of using ${BASH_SOURCE[0]}
directly: if you invoke the script as sh
's argument and your sh
is not aliased to bash
(in my case, on Ubuntu 16.04.5 LTS, it was linked to dash
), it may fail with BASH_SOURCE
variable being empty/undefined. Here's an example:
t.sh:
#!/usr/bin/env bash
echo "\$0: [$0]"
echo "\$BASH_SOURCE: [$BASH_SOURCE]"
echo "\$BASH_SOURCE or \$0: [${BASH_SOURCE:-$0}]"
echo "\$BASH_SOURCE[0] or \$0: [${BASH_SOURCE[0]:-$0}]"
(SuccessfulSuccessfully) runs:
$ ./t.sh
$0: [./t.sh]
$BASH_SOURCE: [./t.sh]
$BASH_SOURCE or $0: [./t.sh]
$BASH_SOURCE[0] or $0: [./t.sh]
$ source ./t.sh
$0: [/bin/bash]
$BASH_SOURCE: [./t.sh]
$BASH_SOURCE or $0: [./t.sh]
$BASH_SOURCE[0] or $0: [./t.sh]
$ bash t.sh
$0: [t.sh]
$BASH_SOURCE: [t.sh]
$BASH_SOURCE or $0: [t.sh]
$BASH_SOURCE[0] or $0: [t.sh]
And finally:
$ sh t.sh
$0: [t.sh]
$BASH_SOURCE: []
$BASH_SOURCE or $0: [t.sh]
t.sh: 6: t.sh: Bad substitution
Resume
As you see, only the third variant: ${BASH_SOURCE:-$0}
- works and gives consistent result under all invocation scenarios. Note that we take advantage of bash's feature of making a reference to an unsubscripted array variable equal to the first array element.