I have a Bash script that needs to know its full path. I'm trying to find a broadly-compatible way of doing that without ending up with relative or funky-looking paths. I only need to support Bash, not sh, csh, etc.
What I've found so far:
The accepted answer to Getting the source directory of a Bash script from within addresses getting the path of the script via dirname $0
, which is fine, but that may return a relative path (like .
), which is a problem if you want to change directories in the script and have the path still point to the script's directory. Still, dirname
will be part of the puzzle.
The accepted answer to Bash script absolute path with OS X (OS X specific, but the answer works regardless) gives a function that will test to see if $0
looks relative and if so will pre-pend $PWD
to it. But the result can still have relative bits in it (although overall it's absolute) — for instance, if the script is t
in the directory /usr/bin
and you're in /usr
and you type bin/../bin/t
to run it (yes, that's convoluted), you end up with /usr/bin/../bin
as the script's directory path. Which works, but...
The readlink
solution on this page, which looks like this:
# Absolute path to this script. /home/user/bin/foo.sh SCRIPT=$(readlink -f $0) # Absolute path this script is in. /home/user/bin SCRIPTPATH=`dirname $SCRIPT`
But readlink
isn't POSIX and apparently the solution relies on GNU's readlink
where BSD's won't work for some reason (I don't have access to a BSD-like system to check).
So, various ways of doing it, but they all have their caveats.
What would be a better way? Where "better" means:
The accepted answer to Getting the source directory of a Bash script from within addresses getting the path of the script via dirname $0 , which is fine, but that may return a relative path (like . ), which is a problem if you want to change directories in the script and have the path still point to the script's ...
To find the full absolute path of the current directory, use the pwd command. Once you've determined the path to the current directory, the absolute path to the file is the path plus the name of the file.
In this case, first, we need the current script's path, and from it, we use dirname to get the directory path of the script file. Once we have that, we cd into the folder and print the working directory. To get the full or absolute path, we attach the basename of the script file to the directory path or $DIR_PATH.
Here's what I've come up with (edit: plus some tweaks provided by sfstewman, levigroker, Kyle Strand, and Rob Kennedy), that seems to mostly fit my "better" criteria:
SCRIPTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
That SCRIPTPATH
line seems particularly roundabout, but we need it rather than SCRIPTPATH=`pwd`
in order to properly handle spaces and symlinks.
The inclusion of output redirection (>/dev/null 2>&1
) handles the rare(?) case where cd
might produce output that would interfere with the surrounding $( ... )
capture. (Such as cd
being overridden to also ls
a directory after switching to it.)
Note also that esoteric situations, such as executing a script that isn't coming from a file in an accessible file system at all (which is perfectly possible), is not catered to there (or in any of the other answers I've seen).
The --
after cd
and before "$0"
are in case the directory starts with a -
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With