This question is related to: Getting the source directory of a Bash script from within - in that question, there is a perfect answer that shows show to get the directory of the currently running bash script (which includes reading the real location of symlinks).
SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null && pwd )"
SOURCE="$(readlink "$SOURCE")"
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
done
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null && pwd )"
This works perfectly, except that it is a lot of boilerplate code. I'm working on a script package that contains lots of small scripts that are using each other. This script package is hosted in a git repo, and it must be location independent. E.g. it should always work the same way, regardless of the directory it was cloned out to. One must be able to clone this repo into many different directories and use them independently. Many scripts are just wrappers around commands, or they are calling other scripts in the same directory, or relative to the containing directory. For example, here is a command that simulates the 'mongo' command, but runs it in a docker container:
#!/bin/bash
set -e
SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null && pwd )"
SOURCE="$(readlink "$SOURCE")"
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
done
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null && pwd )"
# mongo-container is another script that determines the container id
# and it must be referenced relatively to the containing directory
MONGOE="docker exec -ti `${DIR}/mongo-container`"
${MONGOE} mongo "$@"
90% of this code is used to determine the directory of the script, only 10% does something useful. I have about 20 scripts like this. It means that 90% of my bash scripts do nothing just "determine the contaning directory". When I look at them, I almost can't see what they do, because there is so much boilerplate code. There must be a better way, I just can't figure out.
Any ideas?