Get path of current script when executed through a symlink

I have a utility consisting of a couple of directories with some bash scripts and supporting files that will be deployed to several machines, possibly in a different directory on each machine. The scripts need to be able to reference paths relative to themselves, so I need to be able to get the path to the file that’s currently being executed.

I am aware of the dirname $0 idiom which works perfectly when my script is called directly. Unfortunately there is a desire to be able to create symlinks to these scripts from a totally different directory and still have the relative pathing logic work.

An example of the overall directory structure is as follows:

/
 |-usr/local/lib
 |  |-foo
 |  |  |-bin
 |  |  |  |-script.sh
 |  |  |-res
 |  |  |  |-resource_file.txt
 |-home/mike/bin
 |  |-link_to_script (symlink to /usr/local/lib/foo/bin/script.sh)

How can I reliably reference /usr/local/lib/foo/res/resource_file.txt from script.sh whether it is invoked by /usr/local/lib/foo/bin/script.sh or ~mike/bin/link_to_script?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Try this as a general purpose solution:

DIR="$(cd "$(dirname "$0")" && pwd)"

In the specific case of following symlinks, you could also do this:

DIR="$(dirname "$(readlink -f "$0")")"

Method 2

one line:

cd $(dirname $([ -L $0 ] && readlink -f $0 || echo $0))

Method 3

readlink -f doesn’t work for me, I’ve this mistake:

readlink: illegal option -- f
usage: readlink [-n] [file ...]

But this works fine:

DIR="$(dirname "$(readlink "$0")")"
echo $DIR

Method 4

One small addition to the above script. The -P option to pwd follows symlinks

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

Method 5

In my case (on macOS) I had to use:

DIR=$(cd "$(dirname "$(readlink "$0" || echo "$0")")" && pwd)

This is because the symlink or the script behind can both be called by users. So in both cases the original files directory has to be resolved. It works as following:

  • readlink "$0" tries to get the file behind the symlink
  • if the script is no symlink echo "$0" prints the physical location of the script
  • in both cases we have the scrips location which we get the directory name of using dirname
  • then we cd into that directory and print the absolute path using pwd

If you aren’t on macOS just add the -f parameter for readlink.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x