Here are different ways to obtain the realpath of the script. Each have their cons and pros and might have slight differences.
I am listing them here so overtime I can complete the list of cons and pros and what they actually do.
script_root=$(dirname $(readlink -f $0))
# Copyright http://stackoverflow.com/a/7400673/257479
myreadlink() { [ ! -h "$1" ] && echo "$1" || (local link="$(expr "$(command ls -ld -- "$1")" : '.*-> \(.*\)$')"; cd $(dirname $1); myreadlink "$link" | sed "s|^\([^/].*\)\$|$(dirname $1)/\1|"); }
whereis() { echo $1 | sed "s|^\([^/].*/.*\)|$(pwd)/\1|;s|^\([^/]*\)$|$(which -- $1)|;s|^$|$1|"; }
whereis_realpath() { local SCRIPT_PATH=$(whereis $1); myreadlink ${SCRIPT_PATH} | sed "s|^\([^/].*\)\$|$(dirname ${SCRIPT_PATH})/\1|"; }
script_root=$(dirname $(whereis_realpath "$0"))
(not reliable)
# Copyright https://stackoverflow.com/a/13222994/257479
script_root=$(ls -l /proc/$$/fd | grep "255 ->" | sed -e 's/^.\+-> //')
Update: I found an example where this snippet failed. Haven't investigated what the problem was yet.
I use
script_root=$(cd $(dirname "$0") || (echo cannot access $(dirname "$0"); exit -1); pwd)
It's low tech, but will probably work anywhere where there is a decent POSIX style shell, e.g. Linux Subsystem for Windows, although I have not tested that assumption
YMMV