These workstations run the Unix operating system. This document is designed to provide a quick introduction to the commands and concepts you will need to work under Unix.
Your view of the network will depend a great deal on the place where you are doing your work and the facilities provided there for connecting to the network. Some possibilities are:
You may also need to set you terminal's or program's communications parameters. Recommended settings are 8-bits and no parity. Use the highest speed supported by your terminal and modem. The ODU lines will automatically match speeds up to 14,400 baud.
If you are in the Southside Hampton Roads area you can dial in at 683-0001. From the Hampton Roads Peninsula, use 594-7790. These connect you to the ODU Computer Services. At the prompt cc-modem-gw4: You must enter the name of a machine on which you want to work. After entering a machine name, you should get the log-in prompt.
telnet machine-name.DEPT.odu.eduwhere machine-name is a machine in your department and DEPT is your abbreviated department name. Department names include:
setenv term xxxxwhere xxxx is the kind of terminal (e.g., set term=vt100 ). Some people also recommend that you follow this command with
tset -Qwhich resets the terminal. In my own experience, this is usually unnecessary,and I have found that many communications programs don't deal well with this, but try it if your terminal seems to be misbehaving.
Most "dumb" terminals provide for 24 lines of text. Many communications programs, however, allow more. If yours is one of these, you should tell Unix how many lines you are using by giving the command
stty rows nnwhere nn is the number of rows/lines.
yppasswdThis command will first prompt you for your old password (just to check that you really are you!) and then will ask you to type your new password (twice, so that an inadvertent typing mistake won't leave you with a password that even you don't know!).
Whether we like it or not, we need to worry about the security of our computing environment. There are people who would take advantage of this computer system if they had any, or more complete, access to it. This could range from the use of computer resources they have no right to, to the willful destruction and/or appropriation of the information we all have online. In order to maintain the level of security in our computing environment that we need, there are some things we all have to take responsibility for. Even though you may not feel like you personally have much to lose if someone had access to your account or files, you have to realize that as soon as someone gains ANY access to our system, it's 100 times easier for them to gain access to ALL of it. So when you are lax with your own account, you are endangering the work and research of everyone else working here.
Your password is the fundamental element of security not only for your personal account, but for the whole UNIX system that we share. Without an account and password a person has NO access to our system. If someone discovers (or you tell someone) your password, not only will they have access to your personal files, but they will have a much better chance to launch attacks against the security of the entire system.
Your account password is the key to accessing and modifying all of your files. If another user discovers your password, he or she can delete all your files, modify important data, read your private correspondence, and send mail out in your name. You can lose much time and effort recovering from such an attack. If you practice the following suggestions, you can minimize the risk.
A person with local knowledge can also try your spouse's name, pets' names, etc. Your account is vulnerable to this type of cracking unless you choose your password carefully.
'/' / | \ / | \ / | \ / | \ / | \ / | \ / | \ bin home usrThe bin directory contains many of the programs for performing common Unix commands. The usr directory contains many of the data files that are required by those and other commands. Of particular interest, however, is the home directory, which contains all of the files associated with individual users like you and me. Each individual user gets a directory within home bearing their own login name. My login name is zeil.
We can expand our view of the Unix files then as:
'/' / | \ / | \ / | \ / | \ / | \ / | \ / | \ / | \ / | \ bin home usr... / | \ / \ / | \ / \ / | \ / \ cd ls ... zeil ...It may be more precise to say that this directory's name is the empty string "". cd and ls are two common Unix commands, as will be explained later.
Within my own home directory, I have a directory also named "bin", containing my own personal programs. Two of these are called "dgl" and "pcucp". So these files are arranged as:
'/' / | \ / | \ / | \ / | \ / | \ / | \ / | \ / | \ / | \ bin home usr... / | \ / \ / | \ / \ / | \ / \ cd ls ... zeil ... | | bin / | \ / | \ / | \ dgl pcucp ...The full name of any file is given by listing the entire path from the root of the directory tree down to the file itself, with "/" characters separating each directory from what follows. For example, the full names of the four programs in the above diagram are:
/bin/cd /bin/ls /home/zeil/bin/dgl /home/zeil/bin/pcucpThere are some common abbreviations that can be used to shorten file names.
The command/program name is usually not given as a full file name. Instead, certain directories, such as /bin, are automatically searched for a program of the appropriate name. Thus, one can invoke the ls command as either
/bin/lsor simply as
lsAs you type, some characters have a special meaning. For example, if you have entered the first few letters of a file name and hit the "Tab" key, the shell will examine what you have typed so far and attempt to complete the filename by filling in the remaining characters. If the shell is unable to complete the filename, a bell or beep sound will be given. Even in this case, the shell will fill in as many characters as it can.
Most special characters are entered by holding down the "Control" key
while typing a letter. By convention, we designate this by placing
the symbol "^" in front of the name of the second key. For example,
if you have typed zero or more letters of a filename and want to see a
list of what filenames begin with what you have typed, you could type
^D, i.e., hold down the "Control" key and type "d". Some other useful
special keys are:
Upon logging in, your working directory should be your home directory. The command pwd will print the working directory. Give the command
pwdYou should see something like
~yournameNow, let's make a place to play in. mkdir will make a new directory. Enter the command
mkdir playingto create a directory named "playing". The command ls lists the contents of the working directory. More generally, ls directoryname will list the contents of any directory. Give the command
lsand you should see playing listed. In fact, it may be the only thing listed. The command cd is used to change the working directory. Give the command sequence
pwd cd playing pwd cd .. pwd cd ./playing pwdto see this in action.
The cp command copies one or more files. You can give this command as cp file1 file2 to make a copy of file file1, the copy being named file2. Alternatively, you can copy one or more files into a directory by giving the command as
cp file1 file2 : :f:ilen directoryNow try the following:
ls ~public Notice that there are a number of files ending with ".txt". cp ~public/*.txt ~/playing ls ~/playingThe "*" is a wildcard character. It tells the shell to substitute any combination of zero or more characters that results in an existing filename. In cases where there are multiple possibilities, such as this one, the shell forms a list of all the matches. So the cp command actually saw a list of all files in the ~public directory whose names ended in ".txt".
To get a better feel for wildcards, try the following:
ls /usr/include ls /usr/include/*.* List only file names containing a ".". ls /usr/include/f*.* ls /usr/include/*f*.*Here are some other common Unix commands. Try experimenting with these in your ~/playing directory.
lpr -Pprinter fileYou will need to consult your local staff to see what printers are available at other sites.
man commanddisplays the manual page for the given command.
man -k keywordlooks up the given keyword in an index and lists the commands that may be relevant.
emacsThen follow the directions given to bring up the tutorial (i.e., type ^\ followed by "t".). When you are done with the tutorial, here are few extra things you should know about emacs:
Most programs that run under X support a very simple "cut-and-paste" facility. Simply drag the mouse across a block of text in any window while holding down the left mouse button. Then position the mouse into a window where you would like that text to be "typed". Click the middle mouse button, and the selected text will be sent to that window just as if you had typed it yourself.
When emacs is run under X, this cut-and-paste feature is supported, but in a different fashion. Text that has been selected in another window by dragging the mouse can be retrieved in emacs by the command C-Y (^Y). Text that has been "killed" in emacs by C-K, C-W, or M-W can be inserted into other windows by clicking the middle mouse button.
NOTE: Some departments use the X Display Manager (XDM) as a
way to login, thus by passing the step of having to start X Windows.
5.0 Customizing Your Unix Environment
By now, you are probably tired of typing "setenv term..." and other
initial commands each time you log in. Now that you can edit files,
one of the first things to do is to customize your login procedure.
The shell uses two important files to customize behavior. When the shell is started up, it executes the commands in a file called ~/.tcshrc. Now, in a typical Unix session, you may actually be running many copies of the shell at the same time, perhaps without even being aware of it. The first time, however, that a shell is started because you have just logged in, it also executes the commands in a file called ~/.login. NOTE: If your department uses XDM then the .login is never used if you login on the console.
You may or may not already have versions of these files. You can check by giving the commands
cd ~ ls -aIf you don't have either of these, you should make one. If you do, consider changing it as described here. First, let's create a .login file. Enter emacs, and create a file with the following:
if ( "$TERM" == "vt100" __ "$TERM" == "network" ) then set term=vt102 # tset -Q endifInstead of "vt102", you should enter whatever terminal type you use most often. If you find that the tset command has been necessary for you in the past, delete the # character. If you ususually reset the number of lines with stty, add that command as well. Now your terminal kind will be set automatically for you whenever you dial in.
If you would like to automatically run X whenever you are working at the console, add the following lines:
if ("`tty`" == "/dev/console") then echo -n "Entering X windows (Control-C to interrupt)" sleep 5 X endifNOTE: This is not needed for departments running XDM.
Be sure to enter everything exactly as shown above, including the quotes. Note that " is the double-quotation key, and that the ` characters around the word tty are the "backwards" apostrophe (You may need to hunt around on your keyboard to find this one, but it will not be on the same key as the ").
Now let's add a few useful items to the .tcshrc file. Edit your .tcshrc file and insert the following:
setenv EDITOR emacs limit coredumpsize 0 # skip remaining setup if not an interactive shell if ($?USER == 0 __ $?prompt == 0) exit set history=40 set ignoreeof set prompt="`hostname`: " alias cp 'cp -i' alias mv 'mv -i' alias rm 'rm -i' alias ls 'ls -F' alias ff 'find . -name \!* -print'The setenv line indicates that emacs is your editor of choice. Some programs, including the mail program introduced in Section 6, will use this information to load an editor when you have large amounts of text to enter/alter.
Of the remaining lines, the most interesting are the alias commands. These set up "abbreviations" for commands. In this case, we are mainly adding options to familiar commands. The first three aliases add a -i option to the cp, mv, and rm commands. This option causes each command to prompt for a confirmation whenever its action would result in a file being deleted. The fourth alias adds the -F option to all ls commands, making it easier to tell the difference between ordinary files, directories, and executable programs. The final alias sets up a "find-file" command, ff. This will search the current directory and all subdirectories within it for a file matching a given pattern. For example the command sequence
cd ~ ff '*.txt'will list all of your files with the .txt extension. After you have checked these two files and saved them, you will have to log out and then log back in again before they take effect.
There are several programs that you can use to get e-mail. I'll
describe the most basic of these, the Unix mail command here. Later,
you may want to check out the X-Windows mail tool, the mush program,
or the vm command for reading e-mail from within the emacs editor.
6.1 Sending
To send mail to someone with login name name, give the command
mail nameYou will be prompted for a subject line to indicate what your message is about. After that, you begin typing your message on the next line. When you are done, type ^D on a line by itself. You will then be prompted with "Cc:", which allows you to add the login names of other people to whom you would like to send a copy of your message. (Many people like to make a habit of cc'ing a copy to themselves.) If you do not want to send any extra copies, just hit the "Return" key. Your message will then be sent.
As you type your message, you can send special instructions to the mail program by entering any of the following at the start of a line:
To actually read your mail, give the command mail with no arguments. You should see a numbered list of your messages. If not, the command "h" (for headers) will list them. You can then read a message by typing it's number.
After reading the message, you can take any of several actions:
Exactly how you do this depends upon your usual access to the CCPO
network. You may need to try several approaches until you find one
that works well for you.
7.1 Transferring Files
7.1.1 At the console:
If you have physical access to a workstation with a floppy drive, you
may be able to transfer your files via 3.5" floppies. The floppies
must have been previously formatted on an IBM PC compatible machine,
for either 720k or 14.4k capacity.
Look for a workstation with a floppy disk drive (not all have them). The drive is known as 'a:/'. Insert your disk. The command mdir a:/ will display the top directory of the floppy disk contents. You can also specify individual directories via mdir a:/directory.
The command
mcopy unixfiles a:/directorywill copy one or more Unix files into the specified directory of the floppy disk. directory may be omitted to copy into the top directory. If, as is likely to be the case, all of the files being transferred are text no executable programs or compressed files then add the -t option:
mcopy -t unixfiles a:/directoryThe mcopy command can also be used to copy from the floppy into the Unix file system.
mcopy 'a:/file' unixdirectorywill copy a file from the floppy. If file includes wildcard characters, multiple files will be copied. As before, if all the files being transferred are text, then add the -t option.
mcopy -t 'a:/file' unixdirectoryFinally, please note that file names for the floppy disk should be enclosed in apostrophes " (especially if they include wildcards). Unix file names should not.
A command mdel is also available for deleting files on a floppy disk:
mdel 'a:/file'
ftp machine-namewhere machine-name is the "full" Internet name of a Department workstation. This full name is formed by taking the short name (examples are given in Section 2.1.1) and adding ".DEPT.odu.edu", where DEPT is your department's abbreviated name.
You will then be prompted for your login name and your password. After entering those, your next commands should be
hash binaryNow you can use the commands cd, pwd, and ls to navigate the Unix directory structure as if you were in the shell. To get a file from the Unix machine to your local machine, the command is
get filenameTo put a file form your local machine onto the Unix machine, the command is
put filenameNeither the get nor put commands can include wildcards in the filename, but by changing the commands to mget and mput, you are allowed to use wild cards.
To end your ftp session, the command is
quit
The most popular transfer protocols supported on the Department machines are called Kermit, Z-modem, Y-modem, and X-modem. If your communications software gives you a choice of these, you need to balance speed against robustness: the ability to cope with noisy telephone lines. Our personal impression is that in terms of speed, these should be rated, in order from fastest to slowest:
Z-modem, Y-modem, Kermit, X-modemand in terms of robustness, from safest to least safe:
Kermit, Z-modem, Y-modem, X-modemThe popular MSKERMIT program offers a clean command that alters the default settings of the Kermit protocol to make it nearly as fast as Y-modem, at some cost in robustness.
Whatever protocol you choose, you will need to consult the documentation or help for your communications software to determine how to work it on your end of the connection. In this document all I can say is how to invoke the matching protocol on the Department end.
kermit -xThis runs kermit as a remote server, allowing you to immediately issue get/send commands on your local Kermit.
rzThen follow your software's procedure for sending files.To send files from the Department to your machine using Z-modem, give the following command to the Department machine:
sz file1...filenThen follow your software's procedure for receiving files. On both commands, if the files being transferred are all text (no executables or compressed files), add a -a option immediately after the rz/sz command name.
rx filenameThen follow your software's procedure for sending a file. To send files from the Department to your machine using X-modem, give the following command to the Department machine:
sx filenameThen follow your software's procedure for receiving files. Unlike the other protocols, X-modem only allows transfer of a single file at one time.
Some of the transfer methods outlines above will perform this conversion for you if you have told them that the files are text (which explains the -t and -a options recommended above).
If, however, you have transferred files to a Unix system and discover them to be full of ^ M characters (you can see this by viewing the file in emacs), you can use the command
dos2unix file1 file2to produce a new file file2 from file1 by converting the line ends to the Unix format.
On the other hand, if you have transferred files from a Unix system and find that the received files appear to consist of a single, extremely long line, you can use the command
unix2dos file1 file2to get a new file file2 with ^M^J line terminators that can be transferred to your non-Unix machine instead of the original file1 .
Finally please note that, although easily transferred files may
allow you to do most of the work of a programming assignment on your
home PC, do not fall into the trap of believing that you can simply
transfer the source code and submit it unchanged to your instructor
for grading on the Unix system. Different compilers for the same
language often allow a variety of non-standard language extensions (or
because of bugs, fail to properly compile standard language
constructs). Allow yourself ample time (at least a few days) to port
your code from one compiler to another.
8.0 Compilers
8.1 Compiling in the Shell
Now that you know how to create and edit files, you can generate new
programs. The most commonly used languages in the Department at the
moment are FORTRAN, C, and C++. The FORTRAN compiler is f77, and the
most popular C and C++ compilers are gcc and g++.
The simplest case for each compilers involves compiling a single-file program (or a program in which all files are combined by #include statements). For example, use emacs to prepare the following files:
hello.c #includeThe compiler generates an executable program called a.out. If you don't like that name, you can use the mv command to rename it.int main () { printf ("Hello from C!\n"); return 0; } hello.cc #include int main () { cout << "Hello from C++ !" << endl; return 0; } hello.f PRINT*, 'Hello from FORTRAN' END
To compile files and run those programs, the commands are
gcc -g hello.c a.out g++ -g hello.cc a.out f77 -g hello.f a.outWhen you have a program consisting of multiple files to be compiled separately, add a -c option to each compilation. This will cause the compiler to generate a .o file instead of an executable. Then invoke the compiler on all the .o files together without the -c to produce an executable:
gcc -g -c file1.c gcc -g -c file2.c gcc -g -c file3.c gcc -g file1.o file2.o file3.o(Depending upon what else is in the same directory, the last command can often be abbreviated to "gcc -g *.o".) The same procedure works for the g++ and f77 compilers as well.
Another useful option in all three compilers is -D. If you add an option -Dname=value, then all occurrences of the identifier name in the program will be replaced by value. This can be useful as a way of customizing programs without editing them. If you use this option without a value, -Dname, then the compiler still notes that name has been "defined". This is useful in conjunction with compiler directive #ifdef, which causes certain code to be compiled only if a particular name is defined. For example, many programmers will insert debugging output into their code this way:
.. . X := f(X, Y, Z); #ifdef DEBUG writeln ('*** X: ', X); #endif Y := g(X,Z); .. .The output statement in this code will be ignored by the compiler unless the option -DDEBUG is included in the command line when the compiler is run.
Get into emacs and call up one of the "hello" programs. Change it so that it contains one or more syntax errors, and save this file. Now give the emacs command: M-x compile.12 At the bottom of the screen, you will be asked for the compile command. If the suggested command is not what you want (it won't be, the first time you compile), then type in the proper command just as if you were typing it into the shell. emacs will invoke the compiler, showing its output in a window.
In this case, there should be one or more error messages. The
emacs command C-x ` will move you to the source code location of the
first error. Each subsequent use of C-x ` will move you to the next
error location in turn, until all the reported error messages have
been dealt with.13
8.3 Debugging
In the compilation commands given above, the -g option causes the
compiler to emit information useful for a run-time debugger. The
debugger of choice with these compilers is called gdb. The easiest
way to run gdb is, again, from inside emacs.
Try creating a longer program in the language of your choice, and compile it to produce an executable program a.out. From within emacs, look at one of the source code files for that program and then give the command M-x gdb.
At the prompt "Run gdb like this:", type the program name a.out. emacs will then launch gdb, and eventually you will get the prompt "(gdb)" in a window. You can now control gdb by typing commands into the gdb window. The most important commands are:
In addition to the above, the emacs command C-C < moves your view
of the code up the call stack, allowing you to see the caller of the
current procedure/function. The command C-C > moves you back down.
If you change to a window containing the source code and give the
command C-X space, a breakpoint will be set at the line of code where
the cursor is positioned.
9.0 More Shell Games
9.1 Redirection and Pipes
One of the interesting ideas that pervades Unix is that many, if not most, programs can be viewed as "filters" or "transforms" that take a stream of text as input and produce an altered stream of text as output. Many Unix commands are designed to perform relatively trivial tasks, perhaps not very useful by themselves, that can be chained together in interesting and useful ways.
The practical consequence of this is that Unix shells devote special attention to a standard input stream that forms the main input to most programs/commands, and to a standard output stream that forms the main output from most programs/commands. There is actually a second output stream supported by many programs, the standard error stream, used for writing error/debugging messages. The shell attempts to make it easy either to redirect one of these standard streams to a file or to pipe the standard output stream of one program into the standard input of another.
For example, the program wc (for word count) reads text from its input stream and produces as its output stream three number indicating the number of lines, words, and characters that it saw. You could invoke this directly:
wc Hello. How are you? ^Din which case, you would see as output:
2 4 20For this to be very useful, however, we need to make it accept a file as input. This is done by using the < operator in the shell. Think of the < as an arrow indicating data flowing towards the command from a filename:
wc < hello.fwhere hello.f is the file from Section 8.1, produces the output
6 11 85On the output end, the shell operator > directs the standard output into a file (again, think of this as an arrow indicating data flowing into a filename from the command):
wc < hello.f > hello.wcproduces no output on the screen, but creates a file called hello.wc. That file will contain the output
6 11 85of the wc command. The output redirection operator has a couple of important variants. First, the shell generally does not allow you to redirect into an existing file. If you give the command
wc < hello.f > hello.wca second time, the shell will refuse to perform the command. You can force the shell to delete an existing file and create a new one for redirection by changing the > to >!. Second, sometimes we would like to add output to the end of an existing file instead of replacing that file. This is done with the operator >>. So the code sequence
wc < hello.f >! hello.wc wc < hello.f >> hello.wcwould result in a file hello.wc with contents
6 11 85 6 11 85regardless of whether hello.wc had existed previously.
To pipe the output of one command into the input of another, use the shell operator |. A common example of a pipe is to take a command that may have a large amount of output and to pipe it through more to facilitate viewing. For example, try
ls /bin | moreAs you gain facility with a greater variety of Unix text manipulation commands, you will find that redirection and pipes can be a powerful combination. For example, suppose that you have written program myprog that emits a great deal of output, among which might be some error messages starting with the phrase "ERROR:". If you wanted to read only the error messages, you could, of course, just view all the output, watching for the occasional error message:
myprog | moreBut if the program produces a lot of output, this will quickly become tedious. However, the program grep searches its input stream for a given character string,16 emitting at its output only the lines containing that string. By piping through grep, we can limit the output to the part we really want to see:
myprog | grep "ERROR:" | more
Unix allows three forms of access to any file: read, write, and execute. For an ordinary file, if you have read (r) permission, you can use that file as input to any command/program. If you have write (w) permission, you can make changes to that file. If you have execute (x) permission, you can ask the shell to run that file as a program.
The owner of a file can decide to give any, all, or none of these permissions to each of three classes of people:
The ls -l command will show the permissions granted to each class. For example, if you said
ls -l ~/playingyou might see the response
total 315 - rwxrwx- -- 1 zeil 311296 Jul 21 09:17 a.out - rw- rw- -- - 1 zeil 82 Jul 21 09:12 hello.c - rw- rw- -- - 1 zeil 92 Jul 21 09:13 hello.cc - rw- rw- -- - 1 zeil 85 Jul 20 15:27 hello.fLook at the pattern of hyphens and letters at the left. The first character will be a "d" if the file is a directory, "-" if it is not. Obviously, none of these are directories. The next 3 positions indicate the owner's (u) permissions. By default, you get read and write permission for your own files, so each file has an "r" and a "w". a.out is an executable program, so the compiler makes sure that you get execute (x) permission on it. The other files can't be executed, so they get no "x". This way the shell will not even try to let you use hello.f or any of the other source code files as a program.
The next three character positions indicate the group permissions. In this case, the group per- missions are the same as the owner's permissions.
The final three character positions indicate the permissions given to the world (others). Note that in this case, people other than the owner or members of the same group cannot read, write, or execute any of these files.
Directories also can get the same rwx permissions, though the meaning is slightly different. If you have read permission on a directory, you can see the list of files in the directory via ls or other commands. If you have execute permission on a directory, then you can use that directory inside a file name to get at the files it contains. So, if you have execute permission but not read permission on a directory, you can use those files in the directory whose names you already know, but you cannot look to see what other files are in there. If you have write permission on a directory, you can change the contents of that directory (i.e., you can add or delete files).
The chmod command changes the permissions on files. The general pattern is
chmod classpermissions filesUse "+" to add a permission, "-" to remove it. For example, chmod o+x a.out gives everyone permission to execute a.out. chmod g-rwx hello.* denies members of your group permission to do anything at all with the "hello" program source code files.
myprog < test1.dat > test1.dat.out myprog < test2.dat > test2.dat.out myprog < test3.dat > test3.dat.out myprog < test4.dat > test4.dat.out myprog < test5.dat > test5.dat.outNow, you can't execute dotest1, because you don't have execute permission. (Do ls -l dotest1 to see this.) So use the chmod command to add execute permission:
chmod u+x dotest1Now you can execute dotest1 by simply typing
dotest1Most shells provide special facilities for use in scripts. Since these differ from one shell to another, it's a good idea to tell Unix which shell to use when running the script. You do this by placing the command #!/bin/csh in the first line of the script.
One such special feature is the use of the symbol $k to stand for the kth argument given to the script. For example, suppose that we wanted the ability to use a different set of test files each time we used the test script. One approach would be to create a script dotest2, as follows:
#!/bin/csh myprog < $1 > $1.out myprog < $2 > $2.out myprog < $3 > $3.out myprog < $4 > $4.out myprog < $5 > $5.outAfter the appropriate chmod, this could then be invoked as
dotest2 test1.dat test2.dat test3.dat test4.dat test5.dator with any other five test files. Of course, if we want to test with only four files, or with six files, we're out of luck. It would be nicer if we could have the script loop through as many files as we list on the command line each time we run it. Such a script begins to sound more like a program, and in fact most shells provide loops, if's, and other programming language-like statements. Here, for example, is the script dotest3 that will process each argument in turn, however many there are:
In fact, you can list any program there, not just /bin/csh, and Unix will use that program to process the remainder of the lines in the script.
#!/bin/csh foreach file ($*) myprog < $file > $file.out endHere we use another special feature, the use of $ to indicate that we want to retrieve a value from a variable, in this case the variable file which is assigned by the foreach loop. Also, we use $*, which denotes the entire list of arguments given to the script.
After the appropriate chmod, this script could then be invoked as
dotest3 test1.dat test2.dat test3.dat test4.dat test5.dat test6.dator perhaps as easily as
dotest3 test*.datEither way, the foreach statement will loop though all files named in the argument list, setting file to each file name in turn.
The Unix program make is designed to simplify such project management. In a makefile, you record the steps necessary to build both the final file (e.g., your executable program) and each intermediate file (e.g., the .o files produced by compiling a single source code file).
We say that a file file1 depends upon a second file file2 if the file2 is used as input to some command used to produce file1.
When the make program is run, it then checks to be sure that all of the needed files exist, and that each needed file has been updated more recently than all of the files it depends upon. The key bits of information in a makefile, therefore are
Suppose that we are engaged in a project to produce 2 programs, progA and progB. progA is produced by compiling files utilities.c, progA1.cc, and progA2.cc and linking together the resulting .o files. Program progB is produced by compiling file utilities.c and progB1.f and linking together the resulting .o files. All of the .c and .cc files have #include statements for a file utilities.h. Also, both of the .cc files have an #include statement for a file progA1.h.
Here is a makefile for this project. This file should reside in the project directory, and should be called "Makefile" or "makefile".
# Macro definitions for "standard" language compilations # # First, define special compilation flags. These may change when # we're done testing and debugging. FLAGS=-g -DDEBUG # # The following is "boilerplate" to set up the standard compilation # commands: .SUFFIXES: .SUFFIXES: .f .c .cc .h .o .c.o: ; gcc $(FLAGS) -c $*.c .cc.o: ; g++ $(FLAGS) -c $*.c .f.o: ; f77 $(FLAGS) -c $*.f # # Targets: # progA: utilities.o progA1.o progA2.o g++ $(FLAGS) utilities.o progA1.o progA2.o mv a.out progA progB: utilities.o progB1.o f77 $(FLAGS) utilities.o progB1.o mv a.out progB utilities.o: utilities.c utilities.h progA1.o: progA1.cc utilities.h progA1.h progA2.o: progA2.cc utilities.h progA1.h progB1.o: progB1.fIn the "SUFFIXES" area, standard commands are defined for producing a .o file from a .c, .cc, or .f file. Of course these standard commands simply invoke the C, C++, or FORTRAN compilers.
The key information is in the area labelled "Targets". Each target begins with a single line containing the name of the file to produce, a colon, and then a list of all files that serve as inputs to the commands that produce the file. Following that are any number of command lines that give the Unix commands to actually produce the file. Each command line starts with a "Tab" character (invisible in this listing). Command lines are not needed if the standard commands form the "Suffixes" area can be used to build the desired file.
Suppose that, with just this Makefile and the various source code files in your directory, you issued the command make progB. make reads the Makefile and notes that progB depends upon utilities.o and progB1.o. Since neither of these fiels exists, make sets out to create them. utilities.o depends upon utilities.c and utilities.h. Since these files exist and do not themselves depend upon anything else, make will issue the command to create utilities.o from them. This command is the "standard" command for making a .o file from a .c file:
gcc -g -DDEBUG -c utilities.cNext make looks at progB1.o. It depends upon progB1.f which exists and does not depend upon anything else. So make uses the standard command for FORTRAN files:
f77 -g -c progB1.fNow that both .o files have been created, make proceeds to build its main target, progB, using the command lines provided for that purpose:
f77 -g utilities.o progB1.o mv a.out progBand the progB program has been created.
Now suppose that we immediately give the command "make progA" (or just "make", since by default make builds the first target when none is explicitly given). Then the following commands would be performed:
g++ -g -DDEBUG -c progA1.cc g++ -g -DDEBUG -c progA2.cc g++ -g -DDEBUG utilities.o progA1.o progA2.o mv a.out progA
Note that utilities.c is not recompiled, because make would notice that utilities.o already exists and was created more recently than the last time when either utilities.c or utilities.h was changed.
Now, creating a makefile may seem like a lot of trouble the first time that you want to compile your program. The payoff comes while you are testing and debugging, and find yourself making changes to two or three files and then needing to recompile. Which files do you really need to recompile? It can be hard to remember some times, and the resulting errors may be hard to understand. make eliminates this problem (as well as just being easier to type than a whole series of recompilation commands). This explains why, when you give the M-x compile command in emacs, the default compilation command is "make" rather than a direct use of any particular compiler.
When you prepare your own makefiles, you can re-use the first half
of the example above. You should only need to replace the targets. If
you want to test your makefile without actually performing the
commands, add a -n option to your command (e.g., make -n progB) and
make will simply list the commands it would issue without actually
doing any of them.
11.0 Where to Go From Here?
We've only scratched the surface in this document. There are many
more useful commands and programs available on the Department's Unix
machines, and many of the commands that we have covered have
additional options that have not been mentioned here. Remember that
you can use the Unix man command to call up documentation on any
command. The appendix lists a number of additional commands that you
may want to check out as you become more familiar with Unix.
12.0 Unix Command Summary
[]denotes options
{} denotes required argument
^ denotes control key (depress while typing listed letter).
... indicates that command has many options. Use man to learn
about this command.
awk ... a pattern matching and text manipulation language. bg puts process in background after ^z cal [month] {year} displays calendar for that month cal displays calendar for current month cat {filename} displays filename cat [options] -b number the lines, as -n, but omit the line numbers from blank lines. -n precede each line output with its line number. cd [directoryname] changes to directoryname, no argument indicates home directory cd .. changes to directory one above current cp {file1} {file2} copy file1 naming it file2 mv {file1} {file2 or directoryname} move files or rename them date displays date diff {file1} {file2} compares two files, reporting any differences echo repeats line; useful when using * and ? in filenames fg puts first command in background into the foreground grep {pattern} {filename} find pattern in filename head -n Prints the first n lines of its input, ignoring the rest kill [option] {process id #} kill a process -9 kill no matter what exit exit (close) window or xterm lpr {filename} send file to printer for printing lprm {request} {userid} remove a file from the printer queue lpq check status of printer and jobs ls [options] list files -l long form -a all files, including .files -g groups mail see "man mail" man [option] {command} display manual page for command mesg {y or n} enable/disable messages to terminal mkdir {directoryname} create a directory more {filename} list filename one screen at a time nroff,troff ... text formatting programs ps show processes you are running pwd print working directory rm [option] {filename} remove files -i interactive -r recursive (use with caution) rmdir {directoryname} remove directoryname rwho who is on your current network sed ... A non-interactive editor, useful for writing scripts that involve string replacements, line deletions, etc. sort [options] {filename} sort filename -b ignore spaces and tabs -f sort upper- and lower-case together -r reverse the sorting order -o filename save the output of sort in filename -t letter set field separator to letter -u remove duplicate lines ispell {filename} check spelling of filename tail -n Prints the last n lines of its input, tr Replaces/deletes characters ignoring the rest wc [options] {filename} count words, lines, and characters -c characters only -l number of lines only -w number of words only who who is running remote logins on your machine write {user} write message to user, ^d to quit yppasswd change password, follow prompts ? matches any single character in a filename * matches any number of characters in a filename (or no characters) & puts command in background when appended to a command line _ pipe, connects output of one command with input of another > redirects output of a command to a file, erasing current contents of a file >> appends output of a command to an existing file < uses the file as an input for a command ^c aborts process (useful when "hung-up") ^d stops a process or signals "done" on console, indicates logout