Project Inquiry
Published on

Evaluating Glob Patterns for $PATH in bash

The $PATH environment variable does not support glob patterns. If you add something with a glob pattern (e.g. *), bash ignores it. Observe:

# create a couple of executables for testing.
$ mkdir -p /test/foo/bin /test/bar/bin
$ echo "echo 'executable foo'" > test/foo/bin/foo
$ echo "echo 'executable bar'" > /test/bar/bin/bar
$ chmod +x /test/foo/bin/foo /test/bar/bin/bar

# we don't expect the shell to find `foo`,
# because it is not in the `$PATH`.
$ foo
bash: foo: command not found

$ export PATH="/test/*/bin:$PATH"
$ echo $PATH

# we still don't expect the shell to find `foo`,
# because `$PATH` does not support glob patterns.
$ foo
bash: foo: command not found

As you can see, if we add glob patterns directly to our $PATH it simply does not work. However, we can use bash to “evaluate” our glob pattern and proceed to update $PATH with the resulting array of oridinary directories. Fortunately, the (...) construct makes this very easy for us:

$ extra_directories=(/test/*/bin)
$ echo ${extra_directories[@]}
/test/bar/bin /test/foo/bin

$extra_directories is an array with two elements, corresponding to the two bin directories we’ve created above. Next, we have to join the array into a string, using : as the separator. No problem with printf:

$ extra_path=$(printf "%s:" "${extra_directories[@]}")
$ echo $extra_path

$extra_path now contains a valid $PATH string. The last thing we have to do, is to update and export the $PATH variable itself:

$ export PATH="${extra_path}${PATH}"
$ echo $PATH

# both, `foo` and `bar` are now in our `$PATH`:
$ foo
executable foo
$ bar
executable bar

Here is the complete script:

$ extra_directories=(your/*/glob/*/pattern)
$ extra_path=$(printf "%s:" "${extra_directories[@]}")
$ export PATH="${extra_path}${PATH}"

Software: Ubuntu 14.04 LTS with bash (version 4.3.30).