Hi, here is a dull post about the . (source) command. It contains facts. Some of my life was spent finding them out, and the purpose of this post is to hopefully save others from the same fate.
The starting point was the gnome-autogen.sh script that is used from autogen.sh scripts instead of autoreconf to handle detecting gtk-doc and intltool as well as the standard autotools. A couple of modules bundle this file in git as well, which isn’t necessary, and it turns out differences between the way source works in different shells causes slightly confusing things to happen sometimes. The bundled version may be preferred over the system-wide version, depending on your shell, and the phase of the moon.
Here is an abstract test which demonstrates the problem:
mkdir -p in-path
mkdir -p local
cat <<EOF > in-path/foo.sh
#!/bin/sh
echo "I'm in the path"
EOF
chmod +x in-path/foo.sh
cat <<EOF > local/foo.sh
#!/bin/sh
echo "I'm local only"
EOF
chmod +x local/foo.sh
# Here we should run the local copy
cd local
. foo.sh
cd ..
# Now we should run the copy that is in the path instead
PATH=$(pwd)/in-path:$PATH
cd local
. foo.sh
cd ..
rm in-path/foo.sh
rm local/foo.sh
rmdir in-path
rmdir local
What output do you expect?
bash by default searches the path, and then the cwd:
sam@droopy:~$ bash source_observes_path.tests
I'm local only
I'm in the path
However, the autogen.sh starts itself with #!/bin/sh, so bash will actually run POSIX mode:
sam@droopy:~$ sh source_observes_path.tests
source_observes_path.tests: line 20: .: foo.sh: file not found
In Busybox’s default shell (Ash), as a performance optimisation they search the local directory first, which is extra unhelpful.
sam@droopy:~$ busybox sh source_observes_path.tests
I'm local only
I'm local only
However, you can use hush, if you like:
sam@droopy:~$ busybox hush source_observes_path.tests
I'm local only
I'm in the path
In this blog post I’ve tried very hard to convey the inherent dullness of exploring these sorts of irregularities in the way different UNIX shells work. Thank you for your attention.