Back in the old days of multi-architecture Unix environments , generally no two Unix vendors could agree on what should be in your
$PATH
. The core of /bin and /usr/bin was the same, but everyone had their own additional directories ( Solaris had a lot of them ). In addition, different local computing groups had different views on where local programs should go; /usr/local/bin, /local/bin, /opt/<something>/bin, /<group>/bin, and so on. This was a problem for me because I maintained a common set of dotfiles across all of the Unix systems I had accounts on , and I didn't want my
$PATH
to be a giant list of every possible directory on every system. So I needed to trim down a giant master list of possible
$PATH
directories to only the ones that existed on the current system, and to make it harder I wanted to use only shell builtins, in a shell where
test
wasn't a builtin.
Fortunately, there is one thing that has to be a builtin and has to fail if a directory doesn't exist (or isn't usable by you), namely
cd
. Using
cd
as a substitute for '
test -d
' is a bit odd, but it works. My shell has real lists, so I could write this as more or less:
# potential $PATH entries in $candidates
path=`{ tpath=()
for (pe in $candidates)
builtin cd $pe >[1=] >[2=] && tpath=($tpath $pe)
echo $tpath }
(This doesn't work for relative paths, but I didn't have any in my
$PATH
.)
Because all shells have to have
cd
as a builtin, this same trick could be used in pretty much any shell. Bourne style shells make you work a bit harder to put together
$PATH
; at a minimum you need to stick :'s between every element ( cf ), and maybe your equivalent of
$candidates
also uses :'s to separate entries and so you have to split it up on those.
(In a Bourne shell I would make
$candidates
just be quoted and space separated, because that's a lot simpler to deal with. This wouldn't handle a
$PATH
entry that had spaces in it, but you don't normally see those.)
Using
cd
this way is a trick, but tricks are what you're forced into in a minimal shell environment where you don't want to run external programs. In actual practice, I wound up writing a little C program to do this and relying on that on systems that I used frequently enough to compile it for them. The implementation with
cd
was only a fallback for systems and situations without my
isdirs
program.
(This is sort of a followup to a Unix shell trick , which was also about something that I had to do for cross-architecture dotfiles.)
PS: All of this comes from the days when systems were slow enough that you tried to avoid running additional external programs in your shell dotfiles, which is why I wanted to do it all with shell builtins instead of running a lot of
test
s or the like. And most modern shells have
test
as a builtin anyway.