CS449, Introduction to Systems Software, Spring 2007

TA: Ricardo Villamarín-Salomón

Lab #8

Part I  Basic Shell Information

Common commands used in UNIX:

(please see additional handout)

Determining the Shell you are using[1]:

$ echo $SHELL

These are some possible[2] answers:

/bin/sh / Bourne Shell
/bin/csh / C Shell
/bin/ksh / Korn shell
/bin/bash / Bash (“Bourne Again Shell”)
/bin/tcsh / TENEX C shell

Changing your shell for the current session

The following command changes your shell to the Korn Shell:

$ /bin/ksh

Exiting from a shell / closing a session

If you changed your shell using the example above and you want to return to your original shell, simply type exit:

$ exit

Changing your shell “permanently”

$ chsh

Valid login shells are: /bin/bash /bin/tcsh /bin/csh /bin/sh /bin/ksh

Enter the new login shell for <your pitt username> [/bin/bash]:

You have to enter one of the options shown above. This example is specific of UNIXS @ CIS. You may receive different information when running that command in a different computer.

Common features of all shells

·  Store values in variables

·  Execute command files

·  Accept arguments to command files

·  Understand multiple commands typed in sequence

·  Formulate pipes and filters

·  Provide control structures for decision making, like other programming languages

Store values in variables and referencing them

Shells allow you to create variables, assign them values and use them in shell scripts.

Bourne Shell (and compatibles) / $ <varname>=<value>
e.g.,
$ SHELL=/bin/csh
C Shell (and compatibles) / $ set <varname>=<value>
e.g.,
$ set minimum=15
Korn Shell / (same as in Bourne Shell)

To reference the value of a variable, prefix its name with the $ sign, for example:

$ echo $minimum
15

Execute command files

Shell commands can be typed directly at the terminal, like so:

$ date

Thu Mar 15 17:57:46 EDT 2007

Or files can be created using a text editor like pico:

$ pico cmdfile

For a small file, you can use cat (finish with ^D, where ^ means you must press the Control key and hold it while pressing the letter D):

$ cat cmdfile
date
^D

After that, you have to give execution permissions:

$ chmod u+x cmdfile

Once you do that, you can execute the file:

$ ./cmdfile
Thu Mar 15 18:04:10 EDT 2007

You can execute multiple commands in the same command file of course:

$ cat cmdfile
echo "This is a test"
^D

$ ./cmdfile
Thu Mar 15 18:13:16 EDT 2007
This is a test

The contents of the file can be seen using cat:

$ cat cmdfile
date
echo "This is a test"

Accept arguments to command files

You can pass arguments to command files and reference them by prefixing its number with a dollar sign. For example:

$ cat > msg
echo $1
^D
$ chmod u+x msg
$ ./msg CS0449
CS0449

If you were going to accept multiple parameters you can write something like this:

$ cat > list
ls –l $1 $2
^D
$ chmod u+x list
$ ./list msg cmdfile
-rwxr--r-- 1 <usrname> OAKLAND 27 Mar 15 18:13 cmdfile
-rwxr--r-- 1 <usrname> OAKLAND 8 Mar 15 18:23 msg

(the listing for your case may vary)

The command above assumes that you created the files cmdfile and msg as described in previous steps.

Understand multiple commands typed in sequence

There are several options for doing this:

Semicolon (;) / Executes commands in the order that they were typed
Executes the next command only if the execution of the previous one (in the sequence) was successful
|| / Executes the next command only if the execution of the previous one (in the sequence) was not successful
| / Results in the creation of a “pipeline” of commands

Semicolon (;)

This is an example of using a semicolon to execute several commands in sequence:

$ echo Hello > file1; ls file1; cat file1; rm file1; ls file1
file1
Hello
file1: No such file or directory

(the last command fails because rm file1 deleted the file file1)

The & sign

The & between two valid commands results in the next command being implemented only if the first command executed successfully

For example, if we create a file called “temp_file”:

$ cat >temp_file
any content
^D

And then we execute the following commands:

$ cat temp_file > backup_file & echo temp_file & rm temp_file
temp_file

The first command copies the contents of temp_file to backup_file and then prints the text “temp_file”. Finally, it removes the file temp_file. If you attempt to execute the previous line again:

$ cat temp_file > backup_file & echo temp_file & rm temp_file
cat: cannot open temp_file

You get an error. Since the first command failed (cat could not open temp_file because it was removed by the last command in the previous line), the second command (and any other command after it) is not executed (i.e., the text “temp_file” is not printed).

The | | sign

Use of || between two valid commands results in the next command being implemented only if the first command fails. For example, assuming that temp_file does not exist, and you try to execute this sequence:

$ cat temp_file > backup_file || ls -l > temp_file
cat: cannot open temp_file

You receive an error because cat could not find temp_file. However, the second command did get executed and if you attempt the previous sequence again:

$ cat temp_file > backup_file || ls -l > temp_file

You do not get any error. This is because in the previous execution of this sequence, after cat failed, the second command (ls -l > temp_file) was executed and temp_file was created, thus there was no error the second time you attempted to run cat temp_file > backup_file

Formulating the pipeline ( | )

The pipeline is used when we want the output of a command to be fed into the input of another

Example 1: Display the files in the current working directory owned by you, using the command less (displays one screen at a time with scrolling).

$ ls -l | grep "<pitt_usr>" | less

(replace <pitt_usr> above with your actual Pitt’s username but leave the quotes)

Example 2: Display the files in the current working directory owned by you, but in sorted order. Lists the files using the command less

$ ls -l | tr -s ' ' | grep "<pitt_usr>" | cut -d' ' -f 9 | sort -f | less

Provide control structures for decision making, like other programming languages

These are the common control structures:

Construct / Description / Features /
The if - else construct
if command1 executes
then
execute command2
else
execute command3
fi / If command1 succeeds, then the commands between then and else are executed. If not, the commands between else and fi execute.
Example:
if date | grep "Fri"
then
echo "Today is friday!"
fi
The elif construct
if this command executes
then
execute this command
elif this command executes
then
execute this command
else
execute this command
fi / Similar to if - else.
The case construct
case argument in
pattern 1) command1;;
pattern 2) command2;;
esac / Argument is a single value or integer or string
Match patterns are specified in pattern. They must be delimited by a brace
If pattern matches argument, then one or more command following the match pattern are executed, up to the next double semicolon.
Example:
echo "Enter A, B, or C: "
read letter
case "$letter" in
A)
echo "You entered A"
;;
B)
echo "You entered B"
;;
C)
echo "You entered C"
;;
*)
echo "You did not enter A, B, or C"
;;
esac
The for loop
for var in value1, value2
do
commands
done / for loop executes for number of times that value is listed.
value1 is substituted into var the second time.
value2 is substituted into var the second time
commands between do and done are executed for value1, value2 and so on.
Example:
for fruit in apples oranges pears bananas
do
echo "$fruit"
done
echo "Task complete."

References

1.  The J. Ranade Unix Primer (Unix/C). McGraw-Hill Companies.

2.  A Practical Guide to Linux(R) Commands, Editors, and Shell Programming. Mark G. Sobell. Prentice Hall PTR.

-3/7-

[1] We will be using the $ symbol to represent the prompt symbol shown by the shell

[2] The shells are not always located under /bin. In addition, once you change the shell, the variable $SHELL will still print the name of the old shell.