How to Get the Directory Where a Bash Script is Located
Bobby Iliev

Bobby Iliev @bobbyiliev

About: I am a professional DevOps Engineer with a demonstrated history of working in the internet industry. I am an avid Linux lover and supporter of the open-source movement philosophy.

Location:
Sofia, Bulgaria
Joined:
Jul 7, 2019

How to Get the Directory Where a Bash Script is Located

Publish Date: Jul 2 '24
27 9

Hello everyone!

When you're working with Bash scripts, it's often useful to know the directory where the script itself resides. This can be essential for referencing relative paths, ensuring the script works correctly regardless of where it is executed from. Let’s dive into how you can achieve this.

Method 1: Using dirname and $0

The simplest way to get the directory of the script is to use the dirname command in combination with $0. Here's a step-by-step explanation:

  1. $0: This special variable contains the path used to invoke the script. It might be a relative path, an absolute path, or just the script name.
  2. dirname: This command removes the last component from a path, effectively giving you the directory part.

Here’s a small snippet to demonstrate this:

#!/bin/bash

# Get the directory of the script
SCRIPT_DIR=$(dirname "$0")

echo "The script is located in: $SCRIPT_DIR"
Enter fullscreen mode Exit fullscreen mode

Method 2: Resolving the Full Path

If you need the absolute path, especially if the script is run from a relative path, you can combine dirname with readlink:

#!/bin/bash

# Resolve the full path of the script
SCRIPT_DIR=$(dirname "$(readlink -f "$0")")

echo "The script is located in: $SCRIPT_DIR"
Enter fullscreen mode Exit fullscreen mode

Breaking Down the Command

  • readlink -f "$0": This command follows all symlinks and returns the absolute path of the script.
  • dirname "$(readlink -f "$0")": This gives the absolute directory path of the script.

Method 3: Handling Edge Cases

For more complex scenarios, such as when the script is sourced or if it's part of a symlink chain, you might need additional logic to ensure you always get the correct directory.

Here’s an advanced version that handles more edge cases:

#!/bin/bash

# Function to resolve the script path
get_script_dir() {
    local SOURCE=$0
    while [ -h "$SOURCE" ]; do # Resolve $SOURCE until the file is no longer a symlink
        DIR=$(cd -P "$(dirname "$SOURCE")" && pwd)
        SOURCE=$(readlink "$SOURCE")
        [[ $SOURCE != /* ]] && SOURCE=$DIR/$SOURCE # If $SOURCE was a relative symlink, resolve it relative to the symlink base directory
    done
    DIR=$(cd -P "$(dirname "$SOURCE")" && pwd)
    echo "$DIR"
}

# Get the directory
SCRIPT_DIR=$(get_script_dir)

echo "The script is located in: $SCRIPT_DIR"
Enter fullscreen mode Exit fullscreen mode

Conclusion

Getting the directory of the Bash script from within the script itself is a common requirement and can be easily achieved using dirname and $0. For more robust solutions, combining these with readlink can ensure you handle absolute paths and symlinks correctly. By incorporating these methods into your scripts, you can make them more portable and easier to manage.

If you’re interested in learning more about Bash scripting, be sure to check out my free eBook on Bash scripting. It's packed with useful information and examples to help you become a Bash scripting pro!

Happy scripting!

Comments 9 total

  • kuberdenis
    kuberdenisJul 2, 2024

    Great post as always, Bobby!! Would the which command would work 🤔 Maybe if I add my script to /usr/local/bin /bin it will automatically fall into the which command logic, what do you think?

    • Bobby Iliev
      Bobby IlievJul 3, 2024

      Thanks for the feedback @kubeden 🙌

      Yep, the which command can be used to find the location of an executable in your PATH, but it has some limitations for this particular case.

      If you add your script to directories like /usr/local/bin or /bin, which can tell you where it’s located when executed, but it doesn't handle relative paths or symlinks as well as dirname and readlink. Here’s how you might use it:

      #!/bin/bash
      
      # Get the full path of the script
      SCRIPT_PATH=$(which "$(basename "$0")")
      
      echo "The script is located in: $SCRIPT_PATH"
      
      Enter fullscreen mode Exit fullscreen mode

      However, for more robustness, especially with symlinks and relative paths, I’d still recommend using the dirname and readlink approach. This is also particularly helpful if your script is going to be executed by other users on their local machines and you would not know where they would store the script.

      • kuberdenis
        kuberdenisJul 3, 2024

        I think I need to read more about symlinks, relative paths, and why “everything is a file in linux”

        I need to go through your book

  • andrea_fazzi
    andrea_fazziJul 2, 2024

    Thank you!

  • Vladas Saulis
    Vladas SaulisJul 3, 2024

    It was very nice command: whereis .

  • David Cantrell
    David CantrellJul 3, 2024

    An alternative way of resolving symlinks:

    SCRIPT_DIR="$( cd "$(dirname "$0")"; pwd -P)"
    
    Enter fullscreen mode Exit fullscreen mode
  • Hana Manzella
    Hana ManzellaJul 3, 2024

    so much for learning! AI HELP ))

  • Joe
    JoeJul 5, 2024

    I use this:

    function mypath () {
      ## Get the real path of the calling script
      ##  From: https://stackoverflow.com/questions/59895/getting-the-source-directory-of-a-bash-script-from-within/246128#246128
      my_path="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)"
    }
    
    
    Enter fullscreen mode Exit fullscreen mode

    I don't remember the details, but it works.

    I don't have a lot of symlinks to symlinks, so I'm not sure if this would fail when your third method would succeed.

    The reason why I need this at all is that I invoke a lot of scripts from the GUI, and, occasionally, from a special directory. The GUI doesn't have $HOME/bin in its PATH and so scripts that call other scripts have to be able to find them by themselves.

    • Bobby Iliev
      Bobby IlievJul 5, 2024

      This is pretty cool! Thank you for sharing! 👏

Add comment