Top Page

Thomas J. Hardman, Jr

thardman [at] thomashardman.com

Technology

Commandline Interface ("CLI") Tutorial 1

This is a basic tutorial for command-line interface ("CLI") for the Mac OSX "Tiger" operating system as of late 2007. Yet most of this should be quite applicable to any UNIX-like operating system such as Red Hat, CentOS, Slackware, NetBSD, OpenBSD, etc. This covers only the basics. Think of it as a primer.

First, some background, and then some exercises. All of the OSX-specific information assumes that you've installed the "X Code Tools" packages from your installation DVDs. That would include the compiler and the "X windowing environment".

Open a terminal window by clicking on the "terminal" icon in the Dock. A terminal will appear. (If you don't see the "terminal" icon in the Dock, use the Finder to go to "Applications" and within "Applications go to "Utilities". Find the icon for "terminal" and drag it into the Dock.)

The terminal is a window into the command-line interface to the operating system. It's what's called the "shell", rather like the shell of an egg. Inside the egg are the mysteries of the machine, and on the outside are the users, input, and output. If you're "in the shell", that means you're interacting with a layer of abstraction that makes the internals of the operating system and the users intelligible to each other, or at least that is the intention.

In the case of most Unix-like operating systems, the shell will be the "bash shell". There are many varieties of shell, each with their own specialized behaviors, strengths, and weaknesses. Some alternative shells include "sh" (the original shell), "csh" (C-like shell), "tcsh" (a C-like shell that has features of the TCL command language), etc.

The "bash" shell is quite powerful and has an immense command set built into it. A very good, and immense, online reference for it is available at the Linux Documentation Project. From that reference:

This is a practical guide which, while not always being too serious, tries to give real-life instead of theoretical examples. I partly wrote it because I don't get excited with stripped down and over-simplified examples written by people who know what they are talking about, showing some really cool Bash feature so much out of its context that you cannot ever use it in practical circumstances. You can read that sort of stuff after finishing this book, which contains exercises and examples that will help you survive in the real world.

Alternatively, from the commandline in your terminal window into the bash shell, you can type:

man bash
(and then press enter)

That would be a lot of reading either way, so save that for later and let's move on.


First it's important to remember that all UNIX commands have the form of

command [flags] [argument] [optional argument] [optional argument]

That's a command, followed by one space, and then the flags (if any) and then one space, and then any arguments (if any). Generally arguments will be a filename (name of a file). Generally the flags will specify behavior from the command that is different from the default which would occur if the command is given without flags. An example of a command with one flag and one argument would be:

ls -l /bin

'ls' has a default which requires no argument. If the default with no flags is used with an argument, the results will differ from the default with no argument. As they say, "'ls *' is not the same as 'ls'".


At the beginning of every line will be a "prompt" which lets you know that the shell is waiting for input. That prompt should let you know your username, the name of the machine where the shell is running (you could be accessing a shell on a remote machine via the InterNet), and the current working directory. If it isn't printing out the working directory, you can find out by typing

pwd

and then pressing the "enter" key. A directory is what on some systems is called a "folder".

By the way, "pwd" is short for "print working directory". Many UNIX commands have names that originated as abbreviations for longer phrases. It may help you to remember the names if you can remember what they are abbreviating.


You might be curious about what's in the current working directory. If so, you could type

ls

and press the "enter" key, and it will tell you. There are many ways you could list a directory with 'ls'. If you want to know about all of them, you could read 'man ls', but for most people most of the time, the default 'ls' is good enough.

If the current working directory isn't very interesting, you might want to go up a directory. To go up a directory, type

cd ..
and then press "enter". If you list that directory with 'ls', among other things you will see your original working directory that should have been part of your prompt when you opened the terminal window into the shell. If you will look at it, your prompt should have changed to indicate the current working directory.

The characters ".." and "." are special names to the shell, when used in the context of 'cd'. The characters ".." mean "one directory higher". The character "." means "this directory".

If you type "cd .." enough times, what will happen? Eventually you will get to what is called "the root of the filesystem". The filesystem, the system by which the operating system organizes its records, is usually thought of as a large upside-down tree, with lots of branches, with each branch being a directory or sub-directory. That's why we refer to "cd up to the root directory". But you could get there more quickly, by typing

cd /

and that could save a lot of typing "cd .." and so that's the easy, and there for the right, way to do it. The character "/", by itself in the context of 'cd', has the meaning of "root of the filesystem". It can also be the separator between elements of a "full path file name". For example, "/usr/bin" can be read as "from the filesystem root, the 'bin' subdirectory of the directory 'usr'".

The directory you were in when you first opened the terminal window onto the shell is your "home directory". To go straight back there at any time, type "cd" by itself and press the "enter" key. "cd" without a directory argument always returns to the home directory.

You can make directories. Return to your home directory by typing "cd" and then type

mkdir foo
and press "enter" and then 'ls' the directory. A new directory named "foo" should be there. If you type in "ls -l", the listing will have a lot of letters on the left side of the page, and at the very beginning of those letters and dashes is a "d" which means it's a directory.

If you 'cd' into that directory with

cd foo

and 'ls', you probably won't see anything, since you just now made it. You could 'cd' back to your home directory, and remove that new directory by typing

rmdir foo

and pressing "enter". Keep in mind that if you try to remove a directory that is not empty, or if you try to remove the directory you are in at the time, you will get an error message.

You can also 'cd' in other ways. For example, 'cd ../../' would take you up two levels, and 'cd ../whatever' would take you up one level and then one level down into a directory named "whatever", if that directory existed.

A very important note: you don't actually change directories, but you can pretend that you do, and because it makes it a lot easier to work with directories if you pretend that, everyone does. Actually, what is happening is that you are telling the 'bash' shell to reset a pointer. That pointer tells the shell where to read and write data, and it also tells the shell the simulate for you that you "are" somewhere. This is almost entirely for the convenience of the user, so that they won't have to type the entire "path" to a file they are referencing. That could be tedious, and computers are supposed to relieve tedium and make things easier. 'cd' is a function of the shell, rather than a separate command.


"Path" can refer to many things. It can be a path to a file -- in UNIX, everything that stores data is a "file" -- or it can be PATH, a set of directories containing executable files, which is searched by the shell looking for a specific file you wish to execute. That would be the "executable file search path".

Executable files are files which do things; most often they are UNIX "commands", though sometimes they might be scripts. This is entirely different from the immense command set which is internal to the bash (or other) shell. Indeed, the bash (or other) shell is a UNIX command.

You can find out what is your "executable file search path" a couple of ways. The easiest is as follows:

echo $PATH
Of course, don't forget to press "enter". This is the last time I'll bother telling the reader to press "enter", if the command is inset as above, the reader should assume it's a command to be followed by pressing the "enter" key".

You should have seen a result something to the effect of

/bin:/sbin:/usr/bin:/usr/sbin

and that is a list of directories where the shell will look for executable commands. The directories listed are separated by a colon ":".

If you were to type 'ls /bin' then you would get a list of the commands and/or scripts in that directory. If you were to type 'ls /bin/ls' you would see a listing of only the executable command 'ls'. If you were to type 'ls -l /bin/ls' you would get a listing that shows you file type and permissions, file owner, file group, size of the file, date and time of last modification, and the name of the file.

Why is the executable file search path important to the shell? Because it saves you work. If you remembered where the files were, you could spend a lot of time typing in things like '/sbin/ifconfig' or '/bin/hostname'. The environmental variable PATH saves you time and memory. With a properly-set PATH, you could just type 'ifconfig' or 'hostname' and the shell would know where to find, and thus could execute, the command.

You might need to add a search directory to PATH. If, for example, the output of 'echo $PATH' did not include the directory "/sw/bin", it should contain it. You might have to put it in manually, and you would type

export PATH="$PATH:/sw/bin"
and now if you 'echo $PATH', you will see "/sw/bin" in the string. That is good because a lot of software will be living there by the time you are done.

Discerning the difference between PATH and $PATH is left as an exercise for the reader. A Clue: 'export' puts information into the environment. 'echo' in this usage can read information from the environment.

You could also use 'echo' for other things, for example:

echo 'Hello, world!'
$PATH is an "environmental variable", which sometimes is abbreviated to "env vars". You can find out what environmental variables are set, and what those settings are, by entering

env
and examining the output. Env vars include the style of your prompt, the path to your home directory, and many other things. You might need to set the DISPLAY environmental variable to "localhost:0.0" so that programs that use the "X windows graphic interface" will know where to send their output. If you get errors from such programs which tell you "can't open display" you probably need to set that variable, thus:

export DISPLAY="localhost:0.0"
echo $DISPLAY
and probably that program will either run, or die with another error. If it tells you something like "can't contact X server at localhost", you need to start up X by clicking the "X" icon in the Dock at the bottom of the screen. "localhost:0.0" is a special name meaning "first display on the local machine".


All of these things could be put into a script in your home directory, and we'll create the script from the commandline instead of within an editor:

echo "## this is a comment\!" > SCRIPT
echo "## we will set PATH and DISPLAY" >> SCRIPT
echo "export PATH=\"\$PATH:/sw/bin\"" >> SCRIPT
echo "export DISPLAY=\"localhost:0.0\"" >> SCRIPT
echo "echo \"Done\!\"" >> SCRIPT
echo "## we are done now." >> SCRIPT

The character "\" has a special meaning to the shell. It's called an "escape character". It's used here because some other characters such as """ (double quote), "$" (dollars or "string"), or "!" (negation) also have special meanings. They will change the behavior of the command as the command is interpreted by the script, unless they are "escaped" by having the escape character "\" immediately before them. The escape character "\" prevents the following character from being accepted as part of a command. It becomes "just text" instead of a special shell symbol.

Please note that in 'echo' there is a major difference between

echo 'whatever!'

and

echo "whatever!"

When 'echo' is used with the double-quote """, 'bash' shell will evaluate any special characters it finds within the double-quotes. 'echo "Hello, World!"' will exit with an error to the effect of '-bash: !": event not found'. That is because bash shell is trying to use the "!" as the negation of a processing calculation which has not been supplied.

When 'echo' is used with the single-quote "'" (or apostrophe), bash shell does not attempt to evaluate any special characters it finds within the single-quotes. However, if you use single-quotes to display text, be sure to "escape" any apostrophes within the text or you will get results you did not want.

Now that you know this, ask yourself what would happen if you tried to use

export PATH='$PATH:/sw/bin'

instead of

export PATH="$PATH:/sw/bin"

?? Do you think that the second would be properly evaluated by the shell, properly substituting $PATH to have the contents output by 'echo $PATH'? Do you think that the first might set the "executable file search path" to "$PATH:/sw/bin" rather than "/bin:/sbin:/usr/bin:/usr/sbin:/sw/bin? If you think either or both of those things you are correct. Using the single-quotes instead of the double-quotes will "make the environment insane" and you probably won't be able to do anything useful in that particular instance of the shell. You'd have to logout. You might even have to restart the computer. In a production environment, for instance running a corporate web-server, that would be A Bad Thing.

In the SCRIPT, above, the character ">" is an output director. In the first line, it tells the shell to create a new file named SCRIPT and write the output of 'echo to it. In the second line, it is used as ">>" to append output to a file named SCRIPT if that file exists, or if the file doesn't exist to create that file and write the output of 'echo' to it. (It's possible in both cases that there was no output and you would still get a "zero length file", meaning that a space has been reserved within the filesystem for a file, but the file contains no data and has a file length of zero.)

Note that this wouldn't be necessary if you were using an editor instead of the commandline.

To see the script, type

cat SCRIPT

To execute the script as if it were a command, try:

`cat SCRIPT`

Note the special character "`", or "backtick", to the left of the number "1" on your keyboard. The "backtick" (or "reverse apostrophe") will cause a second shell to be spawned within the current shell. It is a good way to save a little time when you want to execute a script, or to call one script from within another script. The alternative in this case would have been:

chmod 700 SCRIPT
bash SCRIPT

It might be useful sometime to read the page at 'man chmod' and 'man chown'. 'chmod' changes file permissions of read, write, and execute for the file owner, group, and other users. 'chmod 700 filename' will set the file "filename" to be readable, writeable, and executable for the owner and to be none of those things to anyone else in the file owner's group, nor for other users who are not a member of the owner's group. Seriously, Read The Fine Manual page at 'man chmod'. 'chown' would change the owner and/or the group of the file, and the command is available only to the system super-user or their delegates through the command 'sudo'.


Sometimes it's good to have an editor to use rather than playing around with escape characters on the commandline. Let's take a look at the file SCRIPT with the editor 'vi':

vi SCRIPT

You should see roughly the same thing on your screen as when you used "cat SCRIPT" to print the contents of the file. (Remember, that's different from "`cat SCRIPT`" to execute SCRIPT.)

'vi' is powerful, simple, completely non-intuitive, and the keystrokes used to control it make very little sense. You just have to memorize a few things. There are much better editors but every UNIX-like operating system has 'vi' and it works the same on all of them.

To quit 'vi' without writing anything to file, press the "ESC" ("escape") button, top left of the keyboard. Then type the "colon" (":") key. At the bottom left of the terminal window, you'll see a colon appear. Type in a "q" and a "!" so that it says q! and then press "enter". 'vi' will exit.

To quit 'vi' and save your work, press ESC, press :, and when the colon appears, type wq and press enter. That means "write and quit".

To move around in the file, you can use the keys HJKL to move left and down and up and right. In some versions of 'vi' you can use the up and down and left and right arrows. 'vi' is not aware of the mouse in most cases.

To add text, press the "a" or "i" buttons, which stand for "append" or "insert". Generally it's best to edit using the "i" mode, but if you're just composing new text, probably "a" is the better mode. To get out of the mode, and back into a mode where you can move around with HJKL or enter other modes, just press ESC.

To delete a letter at a time, position the cursor with HJKL until the cursor is over the letter, and press the "x" key. If you press the "d" key twice, it will take out a whole line. You can search for a word or string of letters with the "/" key.


Now for some fun:

If you have not already done so, get the system administrator (perhaps that is yourself) to install the "X Code Tools" (all packages) from the installation software discs. Then you can download and install "fink" from www.finkproject.org. That website will have basic installation instructions, which are well written. Follow those instruction, and get the system administrator (possibly you) to take root priveleges and install the working product.

Check your PATH to see if it contains "/sw/bin" and if it doesn't, add "/sw/bin" to your PATH.

Now you can use 'fink' to find and build software. Try 'fink update' and wait until it's done. Then try 'fink apropos image' or perhaps 'fink apropos audio'. This should give you a list of things that 'fink' can download from the internet and install for you which can do useful things with images or audio. You could even have 'fink' download the source code for you and build it there, for example you could try
'fink -b source mysql-libs' which ought to download and build the MySQL database (see MySQL.Org).

Once you have things downloaded and installed, they are yours to keep. Play and learn and you will also find yourself with a lot of useful tools, some of which are powerful indeed. Many are the backbone of our modern economy.

Welcome to UNIX Commandline!


Next: Sharing and SMB