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

BashPathScripting

Bash Problem Overview


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.

Bash Solutions


Solution 1 - Bash

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

Solution 2 - Bash

The following also works:

cd "${0%/*}"

The syntax is thoroughly described in this StackOverflow answer.

Solution 3 - Bash

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:

https://stackoverflow.com/questions/1055671/how-can-i-get-the-behavior-of-gnus-readlink-f-on-a-mac

Solution 4 - Bash

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

It's easy. It works.

Solution 5 - Bash

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]}")")"  # cd current directory

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)

Solution 6 - Bash

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.

Solution 7 - Bash

I take this and it works.

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

Solution 8 - Bash

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: https://stackoverflow.com/questions/3373132/get-name-of-directory-wher-script-is-executed)

Solution 9 - Bash

There are a lot of correct answers in here, but one that tends to be more useful for me (making sure a script's relative paths remain predictable/work) is to use pushd/popd:

pushd "$(dirname ${BASH_SOURCE:0})"
trap popd EXIT

# ./xyz, etc...

This will push the source file's directory on to a navigation stack, thereby changing the working directory, but then, when the script exits (for whatever reason, including failure), the trap will run popd, restoring the current working directory before it was executed. If the script were to cd and then fail, your terminal could be left in an unpredictable state after the execution ends - the trap prevents this.

Solution 10 - Bash

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

Solution 11 - Bash

Most answers either don't handle files which are symlinked via a relative path, aren't one-liners or don't handle BSD (Mac). A solution which does all three is:

HERE=$(cd "$(dirname "$BASH_SOURCE")"; cd -P "$(dirname "$(readlink "$BASH_SOURCE" || echo .)")"; pwd)

First, cd to bash's conception of the script's directory. Then readlink the file to see if it is a symlink (relative or otherwise), and if so, cd to that directory. If not, cd to the current directory (necessary to keep things a one-liner). Then echo the current directory via pwd.

You could add -- to the arguments of cd and readlink to avoid issues of directories named like options, but I don't bother for most purposes.

You can see the full explanation with illustrations here:

https://www.binaryphile.com/bash/2020/01/12/determining-the-location-of-your-script-in-bash.html

Solution 12 - Bash

echo $PWD

PWD is an environment variable.

Solution 13 - Bash

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionjameshfisherView Question on Stackoverflow
Solution 1 - BashndimView Answer on Stackoverflow
Solution 2 - BashPaul SchulzView Answer on Stackoverflow
Solution 3 - BashkenorbView Answer on Stackoverflow
Solution 4 - BashDan MouldingView Answer on Stackoverflow
Solution 5 - BashJames McGuiganView Answer on Stackoverflow
Solution 6 - BashAmardeep AC9MFView Answer on Stackoverflow
Solution 7 - BashRobert HuView Answer on Stackoverflow
Solution 8 - BashrodnowerView Answer on Stackoverflow
Solution 9 - BashAndrew ThekenView Answer on Stackoverflow
Solution 10 - Bashuser742030View Answer on Stackoverflow
Solution 11 - BashBinary PhileView Answer on Stackoverflow
Solution 12 - BashMaverick HoldemView Answer on Stackoverflow
Solution 13 - BashChandanView Answer on Stackoverflow