Skip to main content
added 4 characters in body
Source Link
Mark A. Donohoe
  • 29.8k
  • 27
  • 150
  • 303

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.

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}]"

(Successful) 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.

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}]"

(Successfully) 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.

Spelling
Source Link
Zilog80
  • 2.5k
  • 2
  • 17
  • 21

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}]"

(Successful) 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 unsuscriptedunsubscripted array variable equal to the first array element.

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}]"

(Successful) 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 unsuscripted array variable equal to the first array element.

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}]"

(Successful) 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.

Source Link
it-alien
  • 460
  • 6
  • 10

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}]"

(Successful) 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 unsuscripted array variable equal to the first array element.