You'll get your Mac news here from now on...

Help TMO Grow

Subscriber Login

Advertising Info


The Mac Observer Express Daily Newsletter


More Info

Site Navigation

Home
News
Tips
Columns & Editorials
Reviews
Reports
Archives
Search
Forums
Links
Mac Links
Software
Reports
Contact

Mac OS X Command Line 101
by Richard Burton


Son Of Mac OS X Variables
Part XI of this series...
July 12th, 2002

Everyone wants to save the environment, but no one wants to help Mom wash the dishes.
-
P.J. O'Rourke

This series is designed to help you learn more about the Mac OS X command line. If you have any questions about what you read here, check out the earlier columns, write back in the comments below, or join us in the Hardcore X! forum.

In our previous column, we looked at shell variables: what they are, how to set them and unset them, etc. We ended with a quick perusal of reserved shell variables that the shell uses to hold certain values that are used for different parts of the shell. Normally, these are stored in environment variables.

Environment variables are a special type of variable that are used to hold certain system-wide settings for a user. As an example, let's say that you are familiar and comfortable with the vi editor or the emacs editor (not to be mistaken for Apple's new eMac computer). Occasionally, a command-line program will want you to enter data and will use a built-in editor to provide a way to do this. Often a command-line program's default is to use either ed or ex, which shouldn't happen to a dog. It would be nice if this program would be able to say "Okay, operating system, fire off a new process using the user's preferred editor," at which point the operating system says "Right-ho!," looks up your preference, and fires up the appropriate editor. In Unix operating systems, this is done via environment variables. When the program wants to fire up an editor, and wants you to decide which to use, the system goes to a lookup table where it finds where you have set your editor of choice and starts it.

Unix shells allow users to access and alter the values in this lookup table via environment variables. By convention, environment variables are in all capital letters, while shell variables are all lower case. You don't have to follow this convention, of course, when defining your own environment variables. However, it is a de facto standard; all of the 'built-in' environment variables are in all caps. Also, it does prevent confusion ... well, lessens it. So, like a good libertarian, I'm not saying that you have to do it, but I am saying that you really should.

To find out which environment variables are defined in your current shell, either by you or for you, simply use the env Unix command. You will see:

    [localhost:~] dr_unix% env
    HOME=/Users/dr_unix
    SHELL=/bin/tcsh
    USER=dr_unix
    PATH=~/bin/powerpc-apple-darwin:/Users/dr_unix/bin:/usr/local/bin:/usr/bin:/bin
    :/usr/local/sbin:/usr/sbin:/sbin:/mysql/bin:.
    __CF_USER_TEXT_ENCODING=0x1F5:0:0
    TERM=vt100
    TERMCAP=d0|vt100|vt100-am|vt100am|dec vt100:    :do=^J:co#80:li#24:cl=\E[;H\E[2
    J:sf=2*\ED:      :le=^H:bs:am:cm=5\E[%i%d;%dH:nd=2\E[C:up=2\E[A: :ce=3\E[K:cd=5
    0\E[J:so=2\E[7m:se=2\E[m:us=2\E[4m:ue=2\E[m:      :md=2\E[1m:mr=2\E[7m:mb=2\E[
    5m:me=2\E[m:        :rf=/usr/share/tabset/vt100:    :rs=\E>\E[?3l\E[?4l\E[?5l\E
    [?7h\E[?8h\E[;r\E[0m\E(B\E)B\E[2J:   :ks=\E[?1h\E=:ke=\E[?1l\E>:     :ku=\EOA:k
    d=\EOB:kr=\EOC:kl=\EOD:kb=^H: :ho=\E[H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:pt:sr=2*
    \EM:vt#3:xn:   :sc=\E7:rc=\E8:cs=\E[%i%d;%dr:
    TERM_PROGRAM=Apple_Terminal
    TERM_PROGRAM_VERSION=57
    LOGNAME=dr_unix
    HOSTTYPE=macintosh
    VENDOR=apple
    OSTYPE=darwin
    MACHTYPE=powerpc
    SHLVL=1
    PWD=/Users/dr_unix
    GROUP=staff
    HOST=localhost
    ENV_SET=
    MANPATH=/Users/dr_unix/man:/usr/local/share/man:/usr/share/man
    [localhost:~] dr_unix% 
    
... or something like it. You can see that there are quite a few environment variables set when you open a terminal window. What some of them represent should be fairly obvious, such as OSTYPE=darwin, VENDOR=apple, USER=dr_unix, and so on. On the other hand, there is that big, ugly, massive value for TERMCAP. If that one is obvious to you, seek professional help. Now.

(In case you are curious, TERMCAP holds a multitude of settings about your terminal ... which type of terminal you are emulating; what functions do various keys perform, like linking the delete key to the delete action; and so on. Don't worry about it, and don't change it; otherwise, you might do yourself mischief.)

You can create a new environment variable, or change the value of a current environment variable, with the csh/tcsh command setenv:

    setenv VAR value
    
For example,
    [localhost:~] dr_unix% setenv FRED Uncle
    [localhost:~] dr_unix% echo $FRED
    Uncle
    [localhost:~] dr_unix% 
    
Notice that you can use the value of an environment variable just like a shell variable, with the '$' or the '${}' construct to avoid confusion.
    [localhost:~] dr_unix% echo "${FRED} B.S., where were you November 3, 1963?"
    Uncle B.S., where were you November 3, 1963?
    [localhost:~] dr_unix% 
    
[Author's note: Uncle B.S. is copyright Tim Wilson.]

Likewise, you can create an environment variable without assigning it a value.

    [localhost:~] dr_unix% echo $JOE
    JOE: Undefined variable.
    [localhost:~] dr_unix% setenv JOE
    [localhost:~] dr_unix% echo $JOE
    [localhost:~] dr_unix% 
    
This distinction can be important in scripts, because 'undefined' is not quite the same as 'defined but with no value'. Furthermore, if you provide setenv with no arguments, it lists all the environment variables and their values, just like env:
    [localhost:~] dr_unix% setenv
    HOME=/Users/dr_unix
    SHELL=/bin/tcsh
    USER=dr_unix
    PATH=~/bin/powerpc-apple-darwin:/Users/dr_unix/bin:/usr/local/bin:/usr/bin:/bin
    :/usr/local/sbin:/usr/sbin:/sbin:/mysql/bin:.
    __CF_USER_TEXT_ENCODING=0x1F5:0:0
    TERM=vt100
    TERMCAP=d0|vt100|vt100-am|vt100am|dec vt100:    :do=^J:co#80:li#24:cl=\E[;H\E[2
    J:sf=2*\ED:      :le=^H:bs:am:cm=5\E[%i%d;%dH:nd=2\E[C:up=2\E[A: :ce=3\E[K:cd=5
    0\E[J:so=2\E[7m:se=2\E[m:us=2\E[4m:ue=2\E[m:      :md=2\E[1m:mr=2\E[7m:mb=2\E[5
    m:me=2\E[m:        :rf=/usr/share/tabset/vt100:    :rs=\E>\E[?3l\E[?4l\E[?5l\E[
    ?7h\E[?8h\E[;r\E[0m\E(B\E)B\E[2J:   :ks=\E[?1h\E=:ke=\E[?1l\E>:     :ku=\EOA:kd
    =\EOB:kr=\EOC:kl=\EOD:kb=^H: :ho=\E[H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:pt:sr=2*\
    EM:vt#3:xn:   :sc=\E7:rc=\E8:cs=\E[%i%d;%dr:
    TERM_PROGRAM=Apple_Terminal
    TERM_PROGRAM_VERSION=57
    LOGNAME=dr_unix
    HOSTTYPE=macintosh
    VENDOR=apple
    OSTYPE=darwin
    MACHTYPE=powerpc
    SHLVL=1
    PWD=/Users/dr_unix
    GROUP=staff
    HOST=localhost
    ENV_SET=
    MANPATH=/Users/dr_unix/man:/usr/local/share/man:/usr/share/man
    FRED=Uncle
    JOE=
    [localhost:~] dr_unix% 
    
Note that $FRED and $JOE have now shown up. Now, given that you can set an environment variable, you might suspect that you can also unset a variable; and you would be right, you clever person. The unsetenv command does this:
    [localhost:~] dr_unix% unsetenv JOE
    [localhost:~] dr_unix% echo $JOE
    JOE: Undefined variable.
    [localhost:~] dr_unix% 
    
As you might imagine, there are quite a few environment variables that are reserved to have particular meanings in tcsh and csh. The most useful ones in my experience, are:
EDITOR The complete pathname to your prefered command-line editor. Usually this is /usr/bin/vi or /usr/bin/emacs.
HOME Your home directory
HOST The current machine name (tcsh only). Admittedly, this is not too useful if you aren't on a network.
PATH The directories where the shell looks, in order, for commands that you type.
PRINTER Your default line printer.
PWD Your current working directory. (This is what the pwd command uses.)
SHELL Which Unix shell you are running. ( This could be tcsh, csh, ksh, bash, zsh, sh, and so on. Darwin defaults to tcsh.)
USER Your username.
VISUAL Your preferred full-screen editor. Generally /usr/bin/vi or /usr/bin/emacs.
If you have found others to be useful, please let me know.

$PATH deserves special mention. When you type a command at the command line, or in a shell script, tcsh will use $PATH to find the command. $PATH contains a list of directories, seperated by colons. tcsh will look in the first directory; if it finds the command, it runs it, otherwise it moves to the next directory. If it is not found at all, tcsh prints an error message. Consider an example using my $PATH:

    [localhost:~] dr_unix% echo $PATH
    /Users/dr_unix/bin/powerpc-apple-darwin:/Users/dr_unix/bin:/usr/local/bin:/usr/
    bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/mysql/bin:.
    [localhost:~] dr_unix% 
    
If, at the command line, I tell tcsh to run the command my_script, tcsh will look for the file /Users/dr_unix/bin/powerpc-apple-darwin/my_script. If there is no such file, it looks for /Users/dr_unix/bin/my_script, then /usr/local/bin/my_script, and so on, until it finds it or gets through the last directory listed, ./my_script. (Remember that '.' here means 'my current working directory', so the shell is looking for the same as ${PWD}/my_script.) If I don't have a file 'my_script' in any of these directories, the shell prints an error:
    [localhost:~] dr_unix% my_script
    my_script: Command not found.
    [localhost:~] dr_unix% 
    
Also, if you create a shell script that is the same name as another script in your $PATH, which one is run first depends on which is encountered first as the shell sequentially searches the directories listed in $PATH. So not only is it sensible not to create a shell script called ls because it is a standard tool, you can see now exactly how this can cause confusion. If this situation does arise, the which command is useful. It tells you which particular file will be run, if any, when you type in a command:
    [localhost:~] dr_unix% which ls
    /bin/ls
    [localhost:~] dr_unix% which my_script
    my_script: Command not found.
    [localhost:~] dr_unix% 
    
One of the primary reasons that csh was created was that the syntax is similar to the C programming language. The idea was that, by creating a shell with syntax similar to C, the learning curve would be much smaller and less steep. C and the Bourne shell (the first Unix shell) are obviously quite different languages. One of the features of C is that global variables (which are sort of analogous to a shell's environment variables) are not, generally, lower case; in C, those are generally used for macros and definitions. To reconcile this feature of C with this feature of Unix shells, csh has something called "paired variables'.

Paired variables are a combination of a reserved shell variable and a reserved environment variable whose values are tied together. Both variables are set to point to the same spot in memory, so changing the value of one will also change the value of the other. For example, $term and $TERM both refer to the type of terminal one is emulating.

    [localhost:~] dr_unix% echo $term
    vt100
    [localhost:~] dr_unix% echo $TERM
    vt100
    [localhost:~] dr_unix% set term=vt200
    [localhost:~] dr_unix% echo $TERM
    vt200
    [localhost:~] dr_unix% setenv TERM vt100
    [localhost:~] dr_unix% echo $term
    vt100
    [localhost:~] dr_unix% 
    
Note that, though the two values are tied together, the shell variable is still used and manipulated like a normal shell variable; ditto for the environment variable. Note, in the following example, how $PATH and $path are tied together, but each uses its own particular syntax. If we modify $path it alters $PATH as well.
    [localhost:~] dr_unix% echo $PATH
    /Users/dr_unix/bin/powerpc-apple-darwin:/Users/dr_unix/bin:/usr/local/bin:/usr/
    bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/mysql/bin:.
    [localhost:~] dr_unix% set path=($path ~/bin)
    [localhost:~] dr_unix% echo $PATH
    /Users/dr_unix/bin/powerpc-apple-darwin:/Users/dr_unix/bin:/usr/local/bin:/usr/
    bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/mysql/bin:.:/Users/dr_unix/bin
    [localhost:~] dr_unix% setenv PATH "${PATH}:/Users/dr_unix/Desktop"
    [localhost:~] dr_unix% echo $path
    /Users/dr_unix/bin/powerpc-apple-darwin /Users/dr_unix/bin /usr/local/bin 
    /usr/bin /bin /usr/local/sbin /usr/sbin /sbin /mysql/bin . /Users/dr_unix/bin 
    /Users/dr_unix/Desktop
    [localhost:~] dr_unix% 
    
Personally, I don't depend on paired variables because other shells don't use them. Since I use ksh at work and the default on OS X is tcsh, I prefer to use the environment variables for anything environment-related. Again, you don't have to do this, but you will find it easier to move between shells and Unixes (Unici?) if you do so. And this is supposed to be about making life easy, isn't it?

By now you are probably ready to jump in and modify/create your .cshrc and .login files. However, you first must know how to edit files on the command line, which we will start in the next column.

You are encouraged to send Richard your comments, or to post them below.


Most Recent Mac OS X Command Line 101 Columns

Command Line History & Editing Your Commands
November 22nd

Pico: An Easy To Use Command Line Editor
November 1st

Understanding The "grep" Command In Mac OS X
October 4th

Command Line History & Editing Your Commands
September 6th

Mac OS X Command Line 101 Archives

Back to The Mac Observer For More Mac News!


Richard Burton is a longtime Unix programmer and a handsome brute. He spends his spare time yelling at the television during Colts and Pacers games, writing politically incorrect short stories, and trying to shoot the neighbor's cat (not really) nesting in his garage. He can be seen running roughshod over the TMO forums under the alias tbone1.



Today's Mac Headlines

[Podcast]Podcast - Apple Weekly Report #135: Apple Lawsuits, Banned iPhone Ad, Green MacBook Ad

We also offer Today's News On One Page!

Yesterday's News

 

[Podcast]Podcast - Mac Geek Gab #178: Batch Permission Changes, Encrypting Follow-up, Re-Enabling AirPort, and GigE speeds

We also offer Yesterday's News On One Page!

Mac Products Guide
New Arrivals
New and updated products added to the Guide.

Hot Deals
Great prices on hot selling Mac products from your favorite Macintosh resellers.

Special Offers
Promotions and offers direct from Macintosh developers and magazines.

Software
Browse the software section for over 17,000 Macintosh applications and software titles.

Hardware
Over 4,000 peripherals and accessories such as cameras, printers, scanners, keyboards, mice and more.

© All information presented on this site is copyrighted by The Mac Observer except where otherwise noted. No portion of this site may be copied without express written consent. Other sites are invited to link to any aspect of this site provided that all content is presented in its original form and is not placed within another .