Linux / Unix: Shell Script Find Out In Which Directory Script File Resides

I need to find out in which directory my bash script resides so that I can read config file called .backup .ignore .target. For example, if my script resides in >/home/foo/script.sh, I need to read /home/foo/.{backup,ignore,target} files. How do I find out the current directory location and shell script directory location in Bash running on Linux or Unix like operating systems?

Tutorial details
Difficulty Easy (rss)
Root privileges No
Requirements None
Time N/A
You can use any one of the following method to find out the portion of pathname:

  1. basename command – Display filename portion of pathname.
  2. dirname command – Display directory portion of pathname.
  3. Bash parameter substitution.
  4. $0 expands to the name of the shell or shell script.

Examples: Shell script find out which directory the script file resides

The following example display directory path or portion of /home/nixcraft/scripts/foo.sh:

dirname /home/nixcraft/scripts/foo.sh

Sample outputs:

/home/nixcraft/scripts

The following line sets the shell variable i to /home/nixcraft/scripts:

i=`dirname /home/nixcraft/scripts/foo.sh`
echo "$i"

OR

i=$(dirname /home/nixcraft/scripts/foo.sh)
echo "$i"

In bash script use $0 instead of /home/nixcraft/scripts/foo.sh:

#!/bin/bash
script="$0"
basename="$(dirname $script)"
 
echo "Script name $script resides in $basename directory."

Sample outputs:

Script name /tmp/test.sh resides in /tmp directory.

Using bash shell ${var%pattern} syntax

To Remove from shortest rear (end) pattern use the following syntax:

var=${path%/*}

For example:

x="/Users/nixcraft/scripts/bar.sh"
echo "${x%/*}"
y="${x%/*}"
echo "$y"

An updated version of the above script:

#!/bin/bash
# Purpose : Linux / Unix shell script find out which directory this script file resides
# Author : nixCraft <http://www.cyberciti.biz> under GPL v2.x+
# -------------------------------------------------------------------------------------
script="$0"
basename="${script%/*}"
config1="${basename}/.backup"
config2="${basename}/.ignore"
config3="${basename}/.target"
 
echo "Script name $script resides in $basename directory."
echo "Reading config file $config1 $config2 $config3, please wait..."

Run it as:
$ chmod +x /tmp/test.sh
$ /tmp/test.sh

Sample outputs:

Fig.01 Sample run from test.sh

A note about finding physical or real path

You may not get a real physical path and real path may be a symbolic link. To get physical path use realpath command. The realpath command uses the realpath() function to resolve all symbolic links, extra / characters and references to /./ and /../ in path. This is useful for shell scripting and security related applications.

Another recommended option is to use the readlink command to display value of a symbolic link or canonical file name:

#!/bin/bash
# Purpose : Linux / Unix shell script find out which directory this script file resides
# Author : nixCraft <http://www.cyberciti.biz> under GPL v2.x+
# -------------------------------------------------------------------------------------
 
## Who am i? ##
## Get real path ##
_script="$(readlink -f ${BASH_SOURCE[0]})"
 
## Delete last component from $_script ##
_mydir="$(dirname $_script)"
 
## Delete /path/to/dir/ component from $_script ##
_myfile="$(basename $_script)"
echo "Script : $_script"
echo "Directory portion of $_script : $_mydir"
echo "Filename portion of $_script : $_myfile"

Save and close the file. Run it as follows:

./demo.bash
cd /home/vivek/
../../tmp/demo.bash
/tmp/demo.bash

Sample outputs:

Fig.02: Finding real path

See also
  • See man pages for more info – bash(1)
🐧 If you liked this page, please support my work on Patreon or with a donation.
🐧 Get the latest tutorials on SysAdmin, Linux/Unix, Open Source/DevOps topics:
CategoryList of Unix and Linux commands
File Managementcat
FirewallAlpine Awall CentOS 8 OpenSUSE RHEL 8 Ubuntu 16.04 Ubuntu 18.04 Ubuntu 20.04
Network Utilitiesdig host ip nmap
OpenVPNCentOS 7 CentOS 8 Debian 10 Debian 8/9 Ubuntu 18.04 Ubuntu 20.04
Package Managerapk apt
Processes Managementbg chroot cron disown fg jobs killall kill pidof pstree pwdx time
Searchinggrep whereis which
User Informationgroups id lastcomm last lid/libuser-lid logname members users whoami who w
WireGuard VPNAlpine CentOS 8 Debian 10 Firewall Ubuntu 20.04
11 comments… add one
  • Russ Thompson Aug 5, 2013 @ 0:40

    i found aund used the function below. This should be included in the script itself.

    getScriptPath() {
        if [ -d ${0%/*} ]
        then
            abspath=$(cd ${0%/*} && echo $PWD/${0##*/})
            # to get the path only - not the script name - add
            pathOnly=`dirname "$abspath"`
        else
            progdir=`dirname $0`
            cd $progdir
            pathOnly=$PWD
        fi
    
        echo $pathOnly;
        return
    }
    

    Further down in the script I can use $(getScriptPath) as variable, such as

    mysql database <$(getScriptPath)/query.sql
    

    Hope this helps:

    • 🐧 nixCraft Aug 12, 2013 @ 11:40

      Russ, I appreciate that you are sharing your code with us.

  • Mahdi Aug 5, 2013 @ 6:35

    Thank you for this!

  • Michel Nicolas Aug 6, 2013 @ 10:46

    Hello,

    The problem is that method won’t give your the absolute path if it is started with the relative one.
    For example, if my script is launched with ./test.sh I won’t know from the script where am I really residing in the FS.

    So the response is :
    abspath=$(readlink -f $0)

    Then you can do any basename, dirname an other path manipulation on it.

    • 🐧 nixCraft Aug 12, 2013 @ 11:41

      Thanks for the heads up. The faq has been updated. I appreciate your post.

  • Chris F.A. Johnson Aug 18, 2013 @ 23:17

    If a script needs to know where it is located, it is badly designed.

    • Michel Nicolas Aug 19, 2013 @ 5:04

      Chris,

      Can you tell me why would it be badly designed? Jugement without deep knowledge about the facts are useless.

      Nicolas

      • Russ Thompson Oct 16, 2013 @ 15:48

        I feel if a script has to be edited when moved from directory to directory to operate correctly it is badly designed.

        • Chris F.A. Johnson Oct 16, 2013 @ 18:15

          If a script has to be moved from directory to directory, it is badly designed. Scripts should always be placed in a directory in your PATH variable, so they can be called from anywhere.

  • Latchezar Tzvetkoff Oct 16, 2013 @ 12:55

    readlink -f $0 won’t work on Mac OS X.
    A nice one-liner would be

    SCRIPT_PATH=$(cd $(dirname ${0}) && pwd)
    

    It doesn’t resolve the real path, though. For this you’ll need an OS check or something…

    SCRIPT_PATH=$(cd $(dirname ${0}) && pwd)
    echo $SCRIPT_PATH
    if [[ ${OSTYPE} = darwin* ]]; then
    	TEMP=`readlink ${SCRIPT_PATH}`
    	echo $TEMP
    	SCRIPT_PATH=${TEMP:-${SCRIPT_PATH}}
    else
    	SCRIPT_PATH=`readlink -f ${SCRIPT_PATH}`
    fi
    

    Note that OS X’s readlink is not reliable.

  • retro Apr 1, 2017 @ 6:24

    What about:

    #!/bin/bash
    echo "File name: $BASH_SOURCE"
    echo "Dir: $(dirname $BASH_SOURCE)"
    

Leave a Reply

Your email address will not be published. Required fields are marked *

Use HTML <pre>...</pre>, <code>...</code> and <kbd>...</kbd> for code samples.