All Unix systems provide
a basic shell called the Bourne Shell, which is in
/bin/sh
. An extension to the Bourne Shell is the Korn
Shell, which is in /bin/ksh
. (These two shells are named for
the people who wrote them.) An alternate to sh and ksh
that is based on certain features of the C language is called the "C
Shell," which is in /bin/csh
. Finally, the C Shell has
been extended, notably to make better use of the arrow keys during
command entry, in the T-C Shell, which is in /bin/tcsh
.
It's the tcsh that you will be using to enter commands when you use your Unix account.
It's possible to change your default shell, but it's not a good idea because we will assume you are using tcsh in all the examples we give in this course. However, if you want to experiment with the other shells you can execute them just like any other Unix command. For example, to try the Korn shell, just type "ksh" at a shell prompt. You exit a shell by typing the exit command.
The shell is the program that issues a prompt string at the beginning
of a line, waits for you to enter a command, executes the command, and
issues the prompt for you to enter the next command. The prompt string
you will see is "qcunix1>
" and, like everything else, can
be changed to suit your preferences. For the examples of shell commands
we will use "$
" to mean whatever prompt string you have
set up.
Each command line begins with the name of a command, optionally followed by command line arguments, and optionally followed by various operators. Spaces are used to separate the elements of the command line.
When you are typing a command to the tcsh, you can use the up
and down arrow keys to scroll through the history list of commands you
have previously entered that the shell maintains. Use the left and
right arrows to move around within a command line, use
<Backspace>
to erase characters, or just type new
characters into the middle of the line, and press
<Enter>
to run the command.
A command name is either the name of an executable file or the name of
a command that is executed directly by the shell itself. (You can set
up aliases for command names, but we will ignore that for now.) When
you type in a command line, the shell reads it and examines the first word.
If it is the name of a built-in command, the shell executes it
directly, and then issues a prompt for you to type another command. If it
is not the name of a built-in command, the shell searches a number of
standard directories until it finds an executable file with the same
name, and then executes the file. When the file finishes executing,
the shell issues a prompt for another command. The message "command
not found"
means the command name was neither a shell built-in command
nor the name of an executable file in any of the standard
directories.
The list of directories that the shell searches to find executable
files is called the search path. Setting up the search path is
an example of a built-in command. It's one of the commands that is
executed automatically when you log in and the shell starts
executing. The shell processes all the command lines in the file
~/.cshrc
whenever it starts running, and also processes
the commands in ~/.login
when you first log in. See
Pathname Syntax for an explanation of these
file names.
Note: If you log out of your account while a command is running in the background, it continues to run forever! This will not endear you with the people who administer qcunix1, to say the least. The jobs command (a tcsh built-in command) will tell you if you have any background commands running, and the kill command can be used to get rid of background commands.
If you already know about I/O redirection and pipes in DOS, you already know about I/O redirection and pipes in Unix, since DOS adopted the same syntax for the same concepts. Even if you already know about I/O redirection, it's a good idea to read the material here, since tcsh includes some features you might not be familiar with.
Unix programs typically read input from the keyboard and write output
to the terminal screen. You can tell the shell that you want the
program to read its standard input from a file rather than from the
keyboard by redirecting stdin, and you can tell the shell that
you want to write its standard output to a file rather than to the
screen by redirecting stdout. Putting a <
character followed by a file name on the command line redirects stdin,
and putting a >
character followed by a filename
redirects stdout. You can connect stdout from one
program to stdin of another program by putting a |
character between two commands on the same line, which is called a
pipe. Any number of commands can be piped together on one
command line.
The shell will not allow you to redirect stdout to a file that
already exists. (There is an option to override this behavior.)
However, you can redirect stdout so that it will be appended to
the end of an existing file by using >>
instead of
>
as the redirection symbol.
Programs normally write error messages to the stderr output stream rather than to stdout so that the messages will be seen by the user even if stdout is redirected to a file or a pipe. The shell will let you redirect stderr if you want to, though. The syntax is to use >& instead of > before the output file name.
In the C++ programs that you write, the cout
output stream
is connected to stdout, cerr
and clog
go to stderr, and cin
comes from stdin.
You can see some examples of I/O redirection when you read the section on Basic Commands.
The first Unix command you should learn is called man. All the Unix commands are documented in an on-line manual, and the man command is used to look at pages in that manual.
To start with a basic example,
$ man manwill show you the man page for the man command itself. That is, it will tell you how to use the man command. Try it, but don't get intimidated by the volume and density of what you see!. Unix man pages assume you already have a good idea of what you are doing. (If you want a gentler introduction to Unix, you might want to look at the Sobell book.
)
Remember, in the examples, "$ "
represents the prompt that
the shell displays before reading the command line you type in. In
this example, the first man
is the name of the command you
want to run (man) and the second man
is a command
line argument, in this case the name of the command you want to know
about.
You get to the next screenful of man output by pressing the
spacebar, or you can quit man by pressing 'q
'.
Now, let's use I/O redirection to save the output of a man command in a file. In this case, you would redirect stdout:
$ man man > man.outInstead of displaying the information on the screen, it will be saved in a file named
man.out
.For an example of input redirection, we'll use the lp command , which normally prints whatever it reads from the keyboard (stdin) on the printer. You can redirect stdin to come from the a file, though:
$ lp < man.out(This is not a great example because lp would have printed
man.out
without doing input redirection if you had
just typed, "lp man.out
".)Finally, you could use a pipe to print the output of a man command without bothering to build a file:
$ man | lpIn this case, the standard output of the man command doesn't appear on the screen, and it doesn't go to a file. It is connected through the pipe dirctly to the input of the lp command, and gets printed on the printer.
Example: Scroll through the contents of somefile
:
$ more somefileExample: Use a pipe to scroll through a long directory listing output by an ls command:
$ ls /usr/users | moreYou can use more to scroll forward or backwards in a file, or to look for certain words in the file. Type '
?
' for help on
these options at the "more" prompt. Type 'q
' to quit
more before you get to the end of the file.
Example: Search the files named alpha
,
beta
, and gamma
for the string "hello
there".
$ egrep "hello there" alpha beta gammaThe quotation marks are needed because there is a blank inside the string. (Without the quotes the search would be for the word "hello" inside the files
there
, alpha
,
beta
, and gamma
.)
Complicated Example: Let's say you have a project with several
files in it and you think you sometimes spelled a variable
this_thing
and sometimes wrote it thisThing
.
The following command will find all occurrences of either string in all
the files in the current directory:
$ egrep "this_*[tT]hing" *The second asterisk in the example is a wildcard that matches all filenames in the current directory. The first command line argument is enclosed in quotes so the shell will not try to expand the asterisk there into file names. The first argument is the search pattern for egrep, and it says to look for "this" followed by zero or more underscore characters, followed by either a lower or upper case 'T' followed by "hing." The name of each file containing a match, along with all matching lines in the file, will be output.
For more information on egrep (or any other command!) see the man page.
somefile
" in my account:
$ find $HOME -name somefile -printExample: Find all C++ files anywhere in the current directory or below:
$ find . -name "*.cc" -printAt this point, it might be a good idea to become familiar with Unix files and directories so these utilities will make more sense!
$ touch a_new_file.that_i_touched.but_it_is emptyThe name of the file that was created by this example is "
a_new_file.that_I_touched.but_it_is
". The example also
created another file, named "empty
." (Most Unix commands
work just as well on a list of file names as on a single one.) You can
also see that there are two periods in the first file name, and that it
is pretty long. It is a valid Unix file name, though.
Unix keeps track of the time a which a file was last modified, which is the most common use for touch. If you touch a file that already exists, its modification time is changed, which can be useful sometimes when using the make utility that we will be dealing with elsewhere. You usually create new files with a text editor, not with touch. We introduced touch here so we could talk about file names without having to deal with the editor.To look at a list of the files that are in your current directory, use the ls command. All by its self, ls just lists the names of all the files, but there are command line arguments that alter the output of the command. For example,
$ ls -lwill give a "long" listing that includes the name of the file, its size, when it was last modified, and its permissions. (You shouldn't have to worry about permissions for a while, but it is an important feature of the Unix file system.)
There is an old joke about two Unix users who were discussing how arcane the system can be. In particular, they were arguing about how many different meanings a period character has in Unix. One claimed there were 47 different uses for the period, and the second claimed there were 48. They argued for a long time until the first said in exasperation, "OK, you'll just have to list all your 48 ways." "Well," the second one said, "first, you can put one at the end of a sentence, ..." "Stop, stop," the first user said, "you're right. I forgot about that one!" Well, you are about to see your first three uses of periods in Unix.Many times there are a lot of files in a directory that you really aren't interested in. For your convenience, any file that has a name beginning with a period is invisible to the ls command ... unless you use the "-a" argument line option, which tells ls to list all files in the directory. You can use the "-a" option alone or in conjunction with other options. For example, you can get a long listing of all files using either of the following two commands:
$ ls -la $ ls -l -aThe next two uses of periods in Unix are "." and ".." which are the names for the current directory and its parent, respectively. Assuming you know about files and directories in DOS, you know the idea of files and directories in Unix. The main differences between a DOS filesystem and a Unix filesystem are:
/usr/users/vickery
. If your user name is
"abc1qc" your home directory will be /usr/users/abc1qc
.
All the sample code from the textbook is available in the directory
CS-200/Examples
in Dr. Vickery's account. You can refer
to this directory using either the full pathname,
/usr/users/vickery/CS-200/Examples
or by using the
~
(tilde) character to get the shell to supply the
pathname to Dr. Vickery's home directory for you:
~vickery/CS-200/Examples
.
You can refer to your own home directory in three different ways:
~/
at the beginning of a pathname refer
to your home directory.
$HOME
refers to your home
directory. Unfortunately, setting and referencing environment
variables is beyond the scope of this Web page.
~<user ID>
refers to your home
directory if you substitute your own account name for <user
ID>
. This is just the general case of the example given for
accessing Dr. Vickery's home directory.
You can use the pwd command to display the full pathname of your current working directory at any time. Also, tcsh can put the last component of the pathname of the current working directory in your prompt string:
$ set prompt="$USER@qcunix1[%C]> "(Like, $HOME, $USER is a reference to an environment variable, in this case one that will produce your user ID.) You could edit this set command into your
~/.cshrc
file so that your
prompt string would be set up each time you log in.
The following example copies file abc
to def
,
moves file ghi
into the parent of the current working
directory without changing its name, moves file jkl
to the
subdirectory sub
(which must already exist) with the new
name mno
, and finally removes all files used in the
example:
$ cp abc def $ mv ghi .. $ mv jkl sub/mno $ rm abc def ../ghi sub/mnoNOTE: There is no way to "undelete" a file once you have removed it!
For this reason, I strongly suggest that you always use the
"-i
" option with the rm command, which causes it to
ask you to confirm each file you ask to remove. The best way to do
this is to make an alias for the rm command that includes
the -i
option. Type this into your ~/.cshrc
file:
alias rm "rm -i"Now, whenever you type the rm command, the shell will add the
-i
argument before running the command, and you will
be asked for confirmation before each file is deleted.
?
' character
substitutes for any single character, and the '*
'
character substitutes for any sequence of zero or more characters.
Unlike DOS, periods are part of the filename, not separators. So, you
can remove all files in the current directory by typing "rm
*
" instead of "rm *.*
." In fact, "rm
*.*
" will remove only those files that have at least one
period in their names.
Square brackets are used to list specific characters or a range of
characters to substitute into potential file names. For example, the
command, "ls [a-z]*
" will list the names of all files in
the current directory that have names starting with a lower case letter
of the alphabet, and not those that start with an upper case letter, a
digit, or any other character. (Note that the asterisk as a wildcard
matches zero or more occurrences of any character, but as a
pattern match character in egrep it matches zero or more
occurrences of the character that immediately precedes it.)
Wildcards work across subdirectories. The following example will copy
all source files in all subdirectories that have names starting with a
lower case letter into the directory BACKUPS
:
$ cp [a-z]*/*.[ch]* BACKUPS