This question already has an answer here:
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 ist
in the directory/usr/bin
and you're in/usr
and you typebin/../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'sreadlink
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:
- Gives me the absolute path.
- Takes out funky bits even when invoked in a convoluted way (see comment on #2 above). (E.g., at least moderately canonicalizes the path.)
- Relies only on Bash-isms or things that are almost certain to be on most popular flavors of *nix systems (GNU/Linux, BSD and BSD-like systems like OS X, etc.).
- Avoids calling external programs if possible (e.g., prefers Bash built-ins).
- (Updated, thanks for the heads up, wich) It doesn't have to resolve symlinks (in fact, I'd kind of prefer it left them alone, but that's not a requirement).
Considering this issue again: there is a very popular solution that is referenced within this thread that has its origin here:
I have stayed away from this solution because of the use of dirname - it can present cross-platform difficulties, particularly if a script needs to be locked down for security reasons. But as a pure Bash alternative, how about using:
Would this be an option?
The accepted solution has the inconvenient (for me) to not be "source-able":
if you call it from a "
source ../../yourScript
",$0
would be "bash
"!The following function (for bash >= 3.0) gives me the right path, however the script might be called (directly or through
source
, with an absolute or a relative path):(by "right path", I mean the full absolute path of the script being called, even when called from another path, directly or with "
source
")The key is to detect the "
source
" case and to use${BASH_SOURCE[0]}
to get back the actual script.If we use Bash I believe this is the most convenient way as it doesn't require calls to any external commands:
Answering this question very late, but I use:
The simplest way that I have found to get a full canonical path in Bash is to use
cd
andpwd
:Using
${BASH_SOURCE[0]}
instead of$0
produces the same behavior regardless of whether the script is invoked as<name>
orsource <name>
.Simply:
Fancy operators are not needed.