Run a script in the same directory as the current script
BashPathFilepathBash Problem Overview
I have two Bash scripts in the same folder (saved somewhere by the user who downloads the entire repository):
script.sh
is run by the userhelper.sh
is required and run byscript.sh
The two scripts should be in the same directory. I need the first script to call the second one, but there are two problems:
- Knowing the current working directory is useless to me, because I don't know how the user is executing the first script (could be with
/usr/bin/script.sh
, with./script.sh
, or it could be with../Downloads/repo/scr/script.sh
) - The script
script.sh
will be changing to a different directory before callinghelper.sh
.
I can definitely hack together Bash that does this by storing the current directory in a variable, but that code seems needlessly complicated for what I imagine is a very common and simple task.
Is there a standard way to reliably call helper.sh
from within script.sh
? And will work in any Bash-supported operating system?
Bash Solutions
Solution 1 - Bash
Since $0
holds the full path of the script that is running, you can use dirname
against it to get the path of the script:
#!/bin/bash
script_name=$0
script_full_path=$(dirname "$0")
echo "script_name: $script_name"
echo "full path: $script_full_path"
so if you for example store it in /tmp/a.sh
then you will see an output like:
$ /tmp/a.sh
script_name: /tmp/a.sh
full path: /tmp
so
> 1. Knowing the current working directory is useless to me, because I don't know how the user is executing the first script (could be with
> /usr/bin/script.sh
, with ./script.sh
, or it could be with
> ../Downloads/repo/scr/script.sh
)
Using dirname "$0"
will allow you to keep track of the original path.
> 2. The script script.sh
will be changing to a different directory before calling helper.sh
.
Again, since you have the path in $0
you can cd
back to it.
Solution 2 - Bash
$0
is considered unsafe and fragile by many devs. I have found another solution, it is safe for a chain of bash scripts and source
.
If a.sh
needs to execute b.sh
(located in the same folder) using a child bash process:
#!/bin/bash
__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
bash ${__dir}/b.sh
If a.sh
needs to execute b.sh
(located in the same folder) using the same bash process:
#!/bin/bash
__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source ${__dir}/b.sh
Solution 3 - Bash
> Is there a standard way to reliably call helper.sh
from within
> script.sh
? And will work in any Bash-supported operating system?
In most cases, when helper.sh
is in the same directory as script.sh
, you can use in script.sh
command:
. ${0%/*}/helper.sh
Explanation:
$0
stores the name of your process (in most cases it's the full path to your script).
${parameter%word}
removes suffix pattern word
from variable $parameter
(in the command above it removes file name /*
from the full path stored in variable $0
).
If for some reasons (described in other answers) you don't want to use $0
, you can use $BASH_SOURCE
instead:
. ${BASH_SOURCE%/*}/helper.sh
And if you want, you can use source
instead of .
:
source ${BASH_SOURCE%/*}/helper.sh
As for me, it's the easiest way to achieve your goal.
Solution 4 - Bash
You can use the $0
variable. But this won't be as simple as getting current script name:
d=${0%/*}
[ x"$d" = x"$0" ] && d=. # portable variant, use [[ ...]] in bash freely
readonly d # optional, for additional safety
# ... later on
. "$d"/helper.sh
This works well in set -e
case as well.