[bash] How can I set the current working directory to the directory of the script in Bash?

I'm writing a Bash script. I need the current working directory to always be the directory that the script is located in.

The default behavior is that the current working directory in the script is that of the shell from which I run it, but I do not want this behavior.

This question is related to bash path scripting

The answer is


The following also works:

cd "${0%/*}"

The syntax is thoroughly described in this StackOverflow answer.


cd "$(dirname "${BASH_SOURCE[0]}")"

It's easy. It works.


echo $PWD

PWD is an environment variable.


If you just need to print present working directory then you can follow this.

$ vim test

#!/bin/bash
pwd
:wq to save the test file.

Give execute permission:

chmod u+x test

Then execute the script by ./test then you can see the present working directory.


Get the real path to your script

if [ -L $0 ] ; then
    ME=$(readlink $0)
else
    ME=$0
fi
DIR=$(dirname $ME)

(This is answer to the same my question here: Get the name of the directory where a script is executed)


Try the following simple one-liners:


For all UNIX/OSX/Linux

dir=$(cd -P -- "$(dirname -- "$0")" && pwd -P)

Bash

dir=$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)

Note: A double dash (--) is used in commands to signify the end of command options, so files containing dashes or other special characters won't break the command.

Note: In Bash, use ${BASH_SOURCE[0]} in favor of $0, otherwise the path can break when sourcing it (source/.).


For Linux, Mac and other *BSD:

cd "$(dirname "$(realpath "$0")")";

Note: realpath should be installed in the most popular Linux distribution by default (like Ubuntu), but in some it can be missing, so you have to install it.

Note: If you're using Bash, use ${BASH_SOURCE[0]} in favor of $0, otherwise the path can break when sourcing it (source/.).

Otherwise you could try something like that (it will use the first existing tool):

cd "$(dirname "$(readlink -f "$0" || realpath "$0")")"

For Linux specific:

cd "$(dirname "$(readlink -f "$0")")"

Using GNU readlink on *BSD/Mac:

cd "$(dirname "$(greadlink -f "$0")")"

Note: You need to have coreutils installed (e.g. 1. Install Homebrew, 2. brew install coreutils).


In bash

In bash you can use Parameter Expansions to achieve that, like:

cd "${0%/*}"

but it doesn't work if the script is run from the same directory.

Alternatively you can define the following function in bash:

realpath () {
  [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"
}

This function takes 1 argument. If argument has already absolute path, print it as it is, otherwise print $PWD variable + filename argument (without ./ prefix).

or here is the version taken from Debian .bashrc file:

function realpath()
{
    f=$@
    if [ -d "$f" ]; then
        base=""
        dir="$f"
    else
        base="/$(basename "$f")"
        dir=$(dirname "$f")
    fi
    dir=$(cd "$dir" && /bin/pwd)
    echo "$dir$base"
}

Related:

See also:

How can I get the behavior of GNU's readlink -f on a Mac?


cd "`dirname $(readlink -f ${0})`"

I take this and it works.

#!/bin/bash
cd "$(dirname "$0")"
CUR_DIR=$(pwd)

The accepted answer works well for scripts that have not been symlinked elsewhere, such as into $PATH.

#!/bin/bash
cd "$(dirname "$0")"

However if the script is run via a symlink,

ln -sv ~/project/script.sh ~/bin/; 
~/bin/script.sh

This will cd into the ~/bin/ directory and not the ~/project/ directory, which will probably break your script if the purpose of the cd is to include dependencies relative to ~/project/

The symlink safe answer is below:

#!/bin/bash
cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"

readlink -f is required to resolve the absolute path of the potentially symlinked file.

The quotes are required to support filepaths that could potentially contain whitespace (bad practice, but its not safe to assume this won't be the case)


This script seems to work for me:

#!/bin/bash
mypath=`realpath $0`
cd `dirname $mypath`
pwd

The pwd command line echoes the location of the script as the current working directory no matter where I run it from.


Examples related to bash

Comparing a variable with a string python not working when redirecting from bash script Zipping a file in bash fails How do I prevent Conda from activating the base environment by default? Get first line of a shell command's output Fixing a systemd service 203/EXEC failure (no such file or directory) /bin/sh: apt-get: not found VSCode Change Default Terminal Run bash command on jenkins pipeline How to check if the docker engine and a docker container are running? How to switch Python versions in Terminal?

Examples related to path

Get Path from another app (WhatsApp) How to serve up images in Angular2? How to create multiple output paths in Webpack config Setting the correct PATH for Eclipse How to change the Jupyter start-up folder Setting up enviromental variables in Windows 10 to use java and javac How do I edit $PATH (.bash_profile) on OSX? Can't find SDK folder inside Android studio path, and SDK manager not opening Get the directory from a file path in java (android) Graphviz's executables are not found (Python 3.4)

Examples related to scripting

What does `set -x` do? Creating an array from a text file in Bash Windows batch - concatenate multiple text files into one Raise error in a Bash script How do I assign a null value to a variable in PowerShell? Difference between ${} and $() in Bash Using a batch to copy from network drive to C: or D: drive Check if a string matches a regex in Bash script How to run a script at a certain time on Linux? How to make an "alias" for a long path?