You are currently viewing PATH and Other Lists as Environment Variables on UNIX Platforms
Photo by Mengliu Di from Pexels

PATH and Other Lists as Environment Variables on UNIX Platforms

Bash is a popular command line interpreter for many UNIX-like systems, including Linux and Mac, but adding new directories to a search path isn’t fun. In fact, it’s a bit error prone, especially for those new to the command line. Here are five bash commands to make it painless to manage any environment variable that contains elements separated by delimiters.

PATH is an environment variable that contains a list of directories that are searched to find commands that you enter from the command line. The directory list is kept as a string of names separated by colons (:).  There are other environment variables similar to PATH, containing lists of things that the system needs, like MANPATH for manual pages, CDPATH for preferred directories to work from, and more.

I’m assuming that you have a basic familiarity with command lines, shell scripts and bash in particular.

Managing Bash Environment Variables

I’ve written five bash commands to make it easy to manage those environment variables. The scripts defining these commands can be downloaded here. To use them, unzip the file and place the resulting human-readable file named “bash-env-management” somewhere in your “.bashrc” file located in your home directory.  I’ll review all the scripts in a future blog post if you’re interested in writing shell scripts in bash.

In fact, I didn’t actually create these bash commands, I created a small script to create the commands for you. This is described below so you can create commands for your own environment variables.

First, how do you use these variables? Here’s some examples using PATH:

What you Want To Do

Using Standard bash Commands

Some Simple Commands

Show the Directories in PATH

echo $PATH

showpath

Add a Directory to the PATH

export PATH=$PATH:new-directory

addpath new-directory

Insert a Directory to the PATH

export PATH=new-directory:$PATH

inspath new-directory

Delete a Directory from the PATH

export PATH=$(echo “$PATH”|sed -e ‘s/old-directory://’)

delpath old-directory

Move a Directory within PATH to be the first entry

export PATH=$(echo “$PATH”|sed -e ‘s/old-directory://’);export PATH=old-directory:$PATH

inspath old-directory

Move a Directory within PATH to be the last entry

export PATH=$(echo “$PATH”|sed -e ‘s/old-directory://’);export PATH=$PATH:old-directory

addpath old-directory

As you can see, removing an existing entry from the list is painful and will not always work using the standard bash commands shown above. To be specific, the sed command shown here will only work if the “old-directory” is NOT the last entry in the list!

Here’s a summary of the simple scripts:

  1. addpath dir
    Removes duplicate entries of “dir” from PATH then adds “dir” to the end of PATH.
  2. inspath dir
    Removes duplicate entries of “dir” from PATH then inserts “dir” to the beginning of PATH.
  3. delpath dir
    Removes “dir” from PATH.
  4. rempath
    Removes all entries from PATH. This exists for completeness, one can more easily type “unset PATH” to do the same.
  5. showpath
    Lists all directories of PATH in a reasonable way.

The showpath command is a good example of how interactions can be made easier. I’m sure you would agree that the example on the right is easier to understand.

Using standard bash commands
echo $PATH

will show you something like:
/bin:/usr/local/bin:/opt/usr/bin:/usr/local/opt/python/libexec/bin:/usr/X11R6/bin:/opt/Qt/5.12.0/clang_64/bin

Using these new bash commands
showpath

will show you something like:
 1:              /bin
 2:              /usr/local/bin
 3:not readable->/opt/usr/bin
 4:              /usr/local/opt/python/libexec/bin
 5: unavailable->/usr/X11R6/bin
 6:              /opt/Qt/5.12.0/clang_64/bin

Some Examples

In case you’re not convinced, let’s try it out. When you start your command line session, you will probably have the basic PATH directories set.

showpath
 1:              /bin
 2:              /usr/bin

Perhaps you have your own bin directory that contains commands you regularly use. You can add it to the PATH by typing:

addpath ~/bin

Now check the result:

showpath
 1:              /bin
 2:              /usr/bin
 3:              /home/doug/bin

At this point, you decide that your own bin directory should be searched before the system directories. You can insert it at the head of the list. Notice that the directory will be removed from the list then inserted at the top:

inspath ~/bin
showpath
 1:              /home/doug/bin
 2:              /bin
 3:              /usr/bin

You should keep in mind that problems could arise from putting other directories at the head of the PATH list.  If you had a shell script in your bin named “ls” for example, you would be using it instead of the system version, which could lead to some confusion later on.

Commands for Other Environment Variables

The five commands described here are actually created by another command. In fact, the five commands are simply aliases for the commands doing the actual work. The “newlist” command creates the aliases, given the name of the environment variable and the suffix you want to use.

For example, MANPATH contains a list of directories containing manual pages for the UNIX “man” command. You can create commands to manage that list by typing

newlist man MANPATH

This will will create five new commands:

    • insman
    • addman
    • delman
    • remman
    • showman

If MANPATH does not already exist, it will be created.  Here is a synopsis of the newlist command.

usage: newlist CommandSuffix VarName [-e][-n][-q][-v][-sX]
 
The ‘CommandSuffix’ is used to create the alias name, and the VarName is the environment variable containing the list. Items enclosed in brackets are optional.
 
 -e : the constructed aliases will not require the list element to exist in the file system
 -n : the constructed aliases will not require the list element to exist as a directory
 -q : the constructed aliases will work quietly
 -v : the constructed aliases will be verbose
 -sX: the constructed aliases will use X as the delimiter, which is $LIST_SEP, a colon (:) by default
 
Aliases are created to insert, append, delete, reset and show all elements in the list.  The list is created if it doesn’t already exist.

The newlist command should appear in your “.bashrc” file as mentioned earlier, but can also be placed in a “.profile”, “.bash_profile” or similar files. This is a Posix-compliant shell script, so it should work fine with “ksh”, the Korn shell if you’re so inclined.

After including these scripts, make sure do define the lists you want to use.  In my “.bashrc” file, I’ve included the following definitions.

newlist path PATH
newlist man MANPATH
newlist cd CDPATH
newlist lib LD_LIBRARY_PATH

newlist class CLASSPATH -n
newlist maclib DYLD_LIBRARY_PATH
newlist host EPICS_CA_ADDR_LIST -s’ ‘ -e

Here I’ve set up commands to manage the standard PATH, MANPATH and CDPATH environment variables. I do development work on that computer, so I’ve included the LD_LIBRARY_PATH which contains the directories where Linux will search for shared libraries.

For Java development, I include the CLASSPATH variable. This list contains a list of classes that Java will search for, so the “-n” flag indicates that it need not exist as a directory entry in the filesystem.

For MacOS development, I use the DYLD_LIBRARY_PATH which is similar to the Linux LD_LIBRARY_PATH, but I’ve given this the name of “maclib” instead of “lib”. The aliases will then be named “addmaclib”, “delmaclib” and so forth.

For EPICS development, I define a list of host addresses; the “-s” option says that the list is separated by spaces instead of colons, and the “-e” option indicates that there is no corresponding entry in the filesystem. Recall the “-n” option indicates that a directory need not exist.  Incidentally, EPICS is the Experimental Physics and Industrial Control System toolkit.

If you’re interested in how these scripts work in excruciating detail, I’ll be going through them in a future post.