Christoph Schiessl's Blog

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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ # 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
/test/*/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

$ # 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:

1
2
3
$ 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:

1
2
3
$ extra_path=$(printf "%s:" "${extra_directories[@]}")
$ echo $extra_path
/test/bar/bin:/test/foo/bin:

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

1
2
3
4
5
6
7
8
9
$ export PATH="${extra_path}${PATH}"
$ echo $PATH
/test/bar/bin:/test/foo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

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

Here is the complete script:

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

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

comments powered by Disqus