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


Working With Variables In The Shell
Part X of this series...
June 28th, 2002

There is nothing in this world constant, but inconstancy.
-
Jonathon Swift, "Critical Essays upon the Faculties of the Mind""

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.

Variables are a very basic part of any computer language. They allow you to store and manipulate data, of course; but in doing so, they make possible many convenient things, like error checking or setting default behavior of a program (or command line environment). Variables in tcsh are a rather large topic. For now, we will just cover the basics.

There are two types of variables in tcsh: shell variables and environment variables. Shell variables are those known only to the particular shell you are running, be it a shell script or a command line window. While not as useful on the command line as in a shell script, shell variables are too useful to be ignored. (And besides, we want to be able to automate things with shell scripts some day, right?)

In tcsh and csh, a variable's value is set simply by typing

    set variable_name = value
    
For example,
    [localhost:~] dr_unix% set i = 9
    
This creates the variable 'i', if it does not exist yet, and assigns the value of '9' to that variable. You could also define the variable without giving it a value. This can be useful in a script in certain contrived circumstances, or in certain reserved or 'built-in' variables that tcsh uses:
    [localhost:~] dr_unix% set i
    
Now, you might think that, to print out the value of the variable you could just tell the shell to print it:
    [localhost:~] dr_unix% echo i
    i
    [localhost:~] dr_unix% 
    
But you see the problem. The shell needs to differentiate between the character 'i' and the value of the variable 'i'. This is done with a '$', thus:
    [localhost:~] dr_unix% echo i
    i
    [localhost:~] dr_unix% set i = 9
    [localhost:~] dr_unix% echo $i
    9
    [localhost:~] dr_unix% 
    
Now this bit of inconsistency may cause you to ask "So why the heck didn't they just let you say '$i=9' when you set the variable? Huh, Mr. Unix Geek?" And the answer is: I don't know. csh and tcsh do this the same way that the first shell, the Bourne Shell (sh), does it, so I think this is a case of "Well, everyone/shell is doing it." I'm hanged if I know why Stephen Bourne did it like this in the first place, though. However, you are not alone, because Larry Wall asked this, too, when he was creating Perl. Still, we're stuck with it, and to be honest, you'll get used to it very quickly. I just wanted to preempt a lot of e-mails.

By and large, variables are easy to embed within command lines. For example,

    [localhost:~] dr_unix% set spy = Fred
    [localhost:~] dr_unix% echo "I gave the papers to $spy in Munich."
    I gave the papers to Fred in Munich.
    [localhost:~] dr_unix% 
    
And if you want to destroy a variable, just use unset:
    [localhost:~] dr_unix% echo $spy
    Fred
    [localhost:~] dr_unix% unset spy
    [localhost:~] dr_unix% echo $spy
    spy: Undefined variable.
    [localhost:~] dr_unix% 
    
So far so good, but consider the following:
    [localhost:~] dr_unix% echo $i
    9
    [localhost:~] dr_unix% echo "I am on the $ith page now."
    ith: Undefined variable.
    [localhost:~] dr_unix% 
    
You see the problem? tcsh interprets '$ith' to mean 'the value of the variable ith' and not 'the value of the variable i, followed by the letters t and h'. To get around this, you can use the '${}' construct. This tells the shell 'limit the variable name to what appears between the curly braces':
[localhost:~] dr_unix% echo $i
9
[localhost:~] dr_unix% echo ${i}
9
[localhost:~] dr_unix% echo "I am on the ${i}th page now."
I am on the 9th page now.
[localhost:~] dr_unix% 
csh and tcsh also provide modifiers that allow you to extract parts of the variable's value without a lot of rigmarole using things like sed, basename, dirname, and so on. They can be used by either $variable_name:x or ${variable_name:x}, where 'x' is one of the following values:

r Root of value (everything but the extension following the dot)
e Extension of value (the suffix following the dot)
h Head of value (all but last pathname component)
t Tail of value (last pathname component)

Some examples will probably best illustrate their use.

    [localhost:~] dr_unix% set filename = /usr/bin/java-rmi.cgi
    [localhost:~] dr_unix% echo $filename
    /usr/bin/java-rmi.cgi
    [localhost:~] dr_unix% echo $filename:r
    /usr/bin/java-rmi
    [localhost:~] dr_unix% echo $filename:e
    cgi
    [localhost:~] dr_unix% echo $filename:h
    /usr/bin
    [localhost:~] dr_unix% echo $filename:t
    java-rmi.cgi
    
These can be very useful, and again I think the only reason that they aren't so common in shell scripts is that few people know that csh and tcsh offer them.

Before we move on, set has a couple of neat little features that can be handy. First, if you want to set a variable so that you don't accidentally change it, you can use the '-r' option to make it read-only:

    [localhost:~] dr_unix% set -r j=30
    [localhost:~] dr_unix% echo $j
    30
    [localhost:~] dr_unix% set j=31
    set: $j is read-only.
    [localhost:~] dr_unix% 
    
Second, set will let you use variables as arrays if you surround the list of values with parentheses:
    [localhost:~] dr_unix% set k=(Fred Barney Dino)
    [localhost:~] dr_unix% echo $k
    Fred Barney Dino
    [localhost:~] dr_unix% echo $k[1]
    Fred
    [localhost:~] dr_unix% 
    
Also, if you want a list of all defined variables, just type set with neither options nor arguments:
    [localhost:~] dr_unix% set 
    _       set
    
    addsuffix
    argv    ()
    autocorrect
    autoexpand
    autolist
    cdpath  /Users/dr_unix
    correct cmd
    cwd     /Users/dr_unix
    default_tcsh_initdir    /usr/share/init/tcsh
    [... and on and on and on ...]
    
Most of the variables you see here are ones that are created by tcsh when the terminal window was opened. They are known as 'reserved' variables, because each one is 'reserved' by some aspect of the shell. There are many, many of these variables. You could probably go your whole life and never have to worry about most of them. A few, however, are worth noting.

argv is an array which contains a list of the arguments that were passed to the shell when it was created. For a terminal window, it will be blank. But when you want to create a shell script, you can say scriptfile file1 file2 file3 ... and behind the scenes, the shell will do the equivalent of set argv = (file1 file2 file3 ...). This hides a lot of mess and is quite useful ... though not so much from the command line.

cwd is automagically set to your current working directory whenever this changes.

histfile tells the shell in which file to store the commands for the command history. (More on this later, I promise.)

home is the full pathname to your home directory.

path lists the directories that the shell searches through to find the command you type. It is also used by commands like which.

prompt is the prompt you see at the command line. If what you see with the set command is different than what you really see at the prompt, there is formatting going on.

shell can be used to remind yourself, either at the command line or in a script, whether you are running tcsh or csh. It is handy if you are writing a script and tcsh does something slightly different from csh

uid is your user id. It is a number (in my case, 501) that is used to determine who owns a file, etc. Normally, this is not used, because it is easier for humans to remember that ...

user is your username.

Many of the 'reserved' shell variables are tied to particular environment variables. We'll cover that subject next time.

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 .