Third Set of Notes on the C Shell: 1) Wildcards Note that the * can be used to match zero or more characters. This can be useful when generating similar filenames. For example, you might want to see all files with the bak extension using: ls -lA *.bak Similarly, you can use the ? to match exactly 1 character. If you have files temp1 temp2 through temp8, you could list them using: ls -l temp? These capabilities are similar to those in DOS. UNIX also has the ability to match a set or range of characters. See any good UNIX reference book for details. 2) Quoting Double quotes can be placed around items so that they are seen as one item. You have already seen this in earlier example C shell scripts. For example, if you want to echo the message "Hello Hello", you cannot use: echo Hello Hello since echo will see this as echoing 2 Hello's. The blanks are simply seen as separating the 2 parameters to the echo command. However, if double quotes are used, then echo sees it as a single item to echo: echo "Hello Hello" Single quotes also cause the items quoted to be seen as one single item, but they also prevent the C shell from replacing items like $PATH with the value of the PATH variable. Instead, the quoted stuff is not changed at all by the C shell. For an example showing the difference between single and double quotes, try the following C shell program. Note that it requires 1 command line parameter. #! /bin/csh -f # # Filename: quotes1 # echo '$argv[1]' Then run the following C shell program, also using 1 parameter: #! /bin/csh -f # # Filename: quotes2 # echo "$argv[1]" A backslash can be used to prevent the C shell from expanding the single character following the backslash. For example, try comparing the output from: echo * with the output from: echo \* Another example can be seen in the sub script. It uses \^d so that the ^ doesn't get changed by the C shell. The idea is that ^d tells grep to find all lines that begin with a d. These lines of output from the ls -l command are the ones that are directories. Thus this program lists your directories that are inside the current directory. Backquotes can be placed around a command that is to be executed within a C shell script. The results of executing the command are then pasted into that line of the script at this position. See the example C shell script called broadcast for a good example. It contains a line with backquotes around a cat command. A simpler version of this would be the following command that uses elm to mail the file msg to everyone whose login ID is listed in the IDlist file: elm -k `cat IDlist` < msg This line then gets executed as if it were: elm -k ID1 ID2 ID3 etc... < msg 3) I/O in C shell scripts: You can produce output in many ways, as you have already seen. The echo command is useful for printing a message on the screen. You can also redirect output to a file using the > symbol as in: command > filename You can append output to the end of an existing file using: command >> filename You can redirect error messages to a file as in: command >& filename Input can be obtained by using $< in a C shell script. For example, here is a while loop that only allows the user out when either an n or a y is entered: while (1) echo -n "Do you wish to continue(y/n)? " switch ("$<") case "n": set reply = "n" break # breaks out of the loop case "y": set reply = "y" break endsw end See the C shell script input1 for a complete example. 4) Manipulation of pathnames: The C shell provides some useful operators for working with pathnames. For example, a pathname followed by :r gives the root of the pathname, that is, the pathname without any extension on the filename. Suppose you have a variable temp with the value: /u1/cfiles/cshell/tabclear.c Then, the value of $temp:r is: /u1/cfiles/cshell/tabclear For an example, look at the curse shell program. It is a program that a C programmer would use to compile a C program and link in the screen routines provided by the curses library. One feature of most UNIX C compilers is that you tell it the filename to place the compiled code into by using the -o filename option. In this C shell script, the :r operator is used to drop the .c extension from the filename and use this as the file to hold the compiled code. Thus, using the script as in: curse program1.c would compile program1.c and place the code into a file called program1. In a similar way, :e gives any extension, :h gives the head, and :t gives the tail. With our temp variable above, we would get: $temp:e has value: c $temp:h has value: /u1/cfiles/cshell Finally, $temp:t has value: tabclear.c 5) Foreground and background jobs: Normally, a command is executed in the foreground. This is true whether the command is a C shell command, C shell program, executable program, etc. However, it is possible to place many commands in the background by placing a & after the command. A job executing in the background, lets you have the UNIX prompt right back so that you can continue to work on something else. This is called multitasking. Note that it does not make sense to put some jobs into the background (because you must supply input interactively, etc.). If you start a job in the background using: command& The C shell will respond with something like: [1] 257 This indicates that this is job number 1, with process ID 257. A job that is running in the foreground can be stopped temporarily by using CTRL z. You should get the message "Stopped" on the screen. You can then have the job continue in the background by entering: bg %n (where n is replaced with the job number, e.g. 1 in the above example) A foreground job can usually be canceled by using CTRL C, instead of CTRL z. To see the status of your background jobs, use the command: jobs -l (note that this is a letter l, not a number 1) You will see the job number of each background job and whether it is running or stopped. A background job can be moved into the foreground by using: fg %n (replace n with the job number) A running background job can be stopped with the command: stop %n (replace n with the job number) You can cancel a background job with the kill command: kill %n (replace n with the job number) If this fails to work, the following is supposed to be a "sure kill": kill -KILL %n Example: Examine the beep shell program. Run it in the foreground by entering the beep command. It is rather annoying, since it keeps beeping the speaker by echoing a CTRL g (the beep character) to the screen. Use CTRL z to stop it, then use jobs -l to see its job number. Then use kill to kill it off. Use the jobs command again to be sure it is gone. Run beep again. This time use CTRL c to try to cancel it. If this doesn't work, you can always resort to the method above. 6) Notes on advanced C shell scripts: These scripts are at this writing (4/11/99) still available under /u1/cfiles/cshell on acad1. The broadcast C shell script already mentioned above is a good example of how to check that the number of command line parameters is correct, that the needed files exists, etc. Note the explicit use of exit to halt the script with a certain exit value. Use 0 for success, and nonzero for an error. Other programs can check the exit status to see how a script has ended! The cformat C shell script calls the C beautifier program cb to properly indent a C program. Then the output of cb is piped into a homemade tabclear program that replaces each tab with 3 blanks. Note the use of $$. It gives a unique number each time you run the program. This is a great way to name temporary files so that you are sure you won't generate a filename you already have. This program also checks for various possible errors, such as not having write access to the desired file. This is because the formatted program, after being placed in a temporary file, is moved back under the original filename. A backup copy of the original program is also kept. The :r and :e pathname operators are also used. The most advanced example present is the tree C shell program. It prints out (in indented form) the directory tree (starting at the current directory). This program calls a helping program named tree.aux. You may be interested in reading through these 2 files to see if you can figure out how they work, but there is more to this example that can be explained here.