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
DifficultyEasy (rss)
Root privilegesNo
RequirementsNone
TimeN/A
You can use any one of the following method to find out the portion of pathname:

ADVERTISEMENTS

  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

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

Fig.02: Finding real path

See also
  • See man pages for more info – bash(1)
🐧 Get the latest tutorials on SysAdmin, Linux/Unix, Open Source/DevOps topics:
CategoryList of Unix and Linux commands
File Managementcat
FirewallCentOS 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 VPNCentOS 8 Debian 10 Firewall Ubuntu 20.04

ADVERTISEMENTS
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.

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