symlinks

All posts tagged symlinks

I recently needed to keep a Bash script in a centralized location, with many symbolic links to that script sprinkled throughout my repository. I wanted the script be able to determine both the user’s PWD, as well as the true location of the script. Based on all the different suggestions found online, I created a little test script to see how well each suggestion worked:

#!/bin/bash

echo "\$0"
echo $0
echo ""

echo "pwd -P"
pwd -P
echo ""

echo "pwd -L"
pwd -L
echo ""

echo "which \$0"
which $0
echo ""

echo "readlink -e \$0"
readlink -e $0
echo ""

echo "readlink -e \$BASH_SOURCE"
readlink -e $BASH_SOURCE
echo ""

I put this script (test.sh) in ~/ and then created a symlink to it in a different directory. Here are the results.

My friend JT left a comment below to say that using $BASH_SOURCE is probably the better choice than using $0, since $0 can be changed, and is only set equal to the file name by convention.

Directly calling the script from the same directory (/home/matthew/):

matthew@broderick:~$ ./test.sh
$0
./test.sh

pwd -P
/home/matthew

pwd -L
/home/matthew

which $0
./test.sh

readlink -e $0
/home/matthew/test.sh

Directly calling the script from some other directory (/some/other/directory/):

matthew@broderick:~/some/other/directory$ ~/test.sh
$0
/home/matthew/test.sh

pwd -P
/home/matthew/some/other/directory

pwd -L
/home/matthew/some/other/directory

which $0
/home/matthew/test.sh

readlink -e $0
/home/matthew/test.sh

Creating a symlink to ~/test.sh in ~/some/other/directory, and calling it directly (./test.sh):

matthew@broderick:~/some/other/directory$ ln -s ~/test.sh ./test.sh
matthew@broderick:~/some/other/directory$ ./test.sh
$0
./test.sh

pwd -P
/home/matthew/some/other/directory

pwd -L
/home/matthew/some/other/directory

which $0
./test.sh

readlink -e $0
/home/matthew/test.sh

Creating a symlink to ~/test.sh in ~/some/other/directory, and calling it from yet another location:

matthew@broderick:~/some/other/directory$ ln -s ~/test.sh ./test.sh
matthew@broderick:~/some/other/directory$ cd ~/somewhere/else
matthew@broderick:~/somewhere/else$ ~/some/other/directory/test.sh
$0
/home/matthew/some/other/directory/test.sh

pwd -P
/home/matthew/somewhere/else

pwd -L
/home/matthew/somewhere/else

which $0
/home/matthew/some/other/directory/test.sh

readlink -e $0
/home/matthew/test.sh

Conclusion:
So, it looks like “readlink -e $0” will always return the full, non-symlink, “physical” location of the script (regardless of whether or not symlinks are involved). Looks like “pwd” returns the user’s current working directory reliably.