Why are shell scripts are so hard to develop? In NodeJS I could simply do:


and it will always require script relative to the current script. But if I try that in shell/bash:


it will look for script relative to cwd (pwd). Seems the dot means cwd (pwd) and not the directory where current script is located as I was expecting.

line 8: ./script.sh: No such file or directory

How can I execute a script relative to the directory where the current executing script is located?

I have tried

/bin/bash script.sh

but I get the error:

/bin/bash: script.sh: No such file or directory

Then I tried


Got this error

line 8: script.sh: command not found

Only the following solution worked fine, but the problem is that it is unreadable:

$("$(dirname "$(realpath "$0")")/script.sh")

6 Answers 6


Another variant to get script dir:

DIR="$(cd "$(dirname "$0")" && pwd)"

then you can call script with


Unfortunately that is the way to go.

Another way (which I prefer) is to cd into the current dir at the beginning of your scripts like this:

cd $(dirname $0)

As the other answers have indicated, your solution is correct.

  • As the other answers have suggested, you can get the script directory once and use it multiple times.  This may be cleaner and more efficient.

  • As the other answers have suggested, you might not need the realpath.  Can you say why you believe that you need it?

  • You seem to have an extra $( and ) in your solution.

    "$(dirname "$(realpath "$0")")/script.sh"

    should be enough …

  • … except there’s a really subtle corner case that nobody else pointed out.  Let’s homogenize the other answers:

    DIR="$(dirname "$(realpath "$0")")"

    If the “current script” is in the root directory (e.g., it is /first_script), and assuming that realpath doesn’t have any effect, we will get DIR="/", so the


    line will be expanded as




    This is typically equivalent to /script.sh.  But Unix (POSIX) reserves the right to treat // at the beginning of a pathname specially.  It is infinitesimally safer to do

    DIR="$(dirname "$(realpath "$0")")"/

    with an (extra, explicit) / at the end of the definition of DIR.  If $0 is /first_script, DIR will be set to //, and "$DIR"/script.sh will be expanded as ///script.sh, which is guaranteed to be equivalent to /script.sh.  And if $0 is something more common, like /foo/bin/first_script, then DIR will be set to /foo/bin/, and "$DIR"/script.sh will be expanded as /foo/bin//script.sh, which is also guaranteed to be equivalent to /foo/bin/script.sh.


In most cases, when script.sh is in the same directory, you can use just:


$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 you don't want to use $0, in bash you can use $BASH_SOURCE instead:


As for me, these are the easiest ways to achieve your goal.


Improving on the Answer from Mikael Kjær.

I had problems handling path with spaces in them but was able to solve it using

cd "$(dirname "$0")"

$0 refers to your current script and dirname $0 will get the directory name of your current script (the full path without the file name)

so you can do it like this:

$(dirname $0)/script.sh
  • 1
    Welcome to the site, and thank you for your contribution. Please note that the "backtick"-style for command substitutions is discouraged and the new $( ... )-style is now recommended.
    – AdminBee
    Commented Oct 29, 2020 at 9:44
  • 1
    (1) This is a subset of the answer that was presented in the question! Do you claim that realpath is totally unnecessary in this situation? Can you justify such a claim?  (2) You should learn why people use quotes. Commented Oct 30, 2020 at 6:40

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .