Now where did I put that file...

Hacking on the backup scripts at work, we realized that all the scripts had hard-coded paths to the installation directory. I could have just made the changes on a new branch (actually, I did), but anything that can be done can be overdone.

Original scripts:


. /path/to/here/config

In PHP, I would have just used something along the lines of dirname(__FILE__). Bash kind-of has an analog of __FILE__ with $0, which works great, except that this script is meant to be run from cron:

ln -s /usr/local/bin/backup /etc/cron.daily/

In this instance, $0 is /etc/cron.daily/backup, which obviously isn't going to work correctly.

Turns out, there's a utility readlink for exactly this purpose. If the argument is a symbolic link, it prints just the target to stdout. Otherwise, it exits with error code 1. So, getting dirname(__FILE__) in bash makes the script start out:


. "$(dirname $(readlink $0 || echo $0))/config"

Either $0 is a symlink, and we grab the path to where it points, or it's a real file, and we just echo it. Either way, what gets passed to dirname is a real file, and so we get the correct path whether the script runs from cron, or logged into the shell.