Notes Home

CA644, System Software
Table of Contents

Shell, Part 1

CA644, System Software

Dr. Niall McMahon


If you print these slides, think about using two pages per sheet although don't worry too much about it!


Dr. Niall McMahon
Drawing on previous work by:
Dr. Michael Scriney
Dr. Long Cheng
And sources credited in the references.
Autumn 2022.

Unix and Linux

We will talk more about the history and development of Unix and Linux as well as its structure soon. First, let's get started with using it.

Running Unix/Linux-based Operating Systems in the Labs

There are a few different ways to run Linux when you're on campus:

In the Labs

  1. Re-start a lab machine.
  2. Select a Linux distribution (Ubuntu or Debian).
  3. Log in.


The School of Computing's Termcast deployment allows browser-based access to a Unix/Linux environment on a physical server in the school - it's a browser-based terminal and Linux shell. You can get access at Log in with your School of Computing credentials, i.e. your account.

You can get help with termcast here. All of this was implemented by Stephen Blott.

Running Unix/Linux-based Operating Systems at Home

  • If you have an old PC, you can install Linux. Try Ubuntu or Debian.
  • If you have an Apple Macintosh, you can start a terminal in macOS. macOS is Unix-based, i.e. it's Unix-like, and so shares much core functionality with Linux.
  • If you have a Chromebook, you can set up Linux for ChromeOS, called Crostini. ChromeOS is Linux-based, i.e. a Unix-like OS.
  • You can access the School's Termcast implementation from home. See notes above about accessing Linux in the labs.
  • You can buy a Raspberry Pi. Raspberry Pis are inexpensive PCs that come shipped with the Raspberry Pi / Raspbian OS. Raspberry Pi OS is based on Debian, the Linux distribution.
  • If you usually run MS Windows, try the Windows Subsystem for Linux (WSL). WSL is heavy on resources and heavier than Linux alone would be, obviously. But it is Linux.
  • Another MS Windows option is Cygwin. Cygwin is not Linux but it is a "large collection of GNU and Open Source tools which provide functionality similar to a Linux distribution on Windows". So you can get to know your way around Linux syntax.
  • Depending on your expertise, you could create a cloud-based virtual machine (VM) using Google's Compute Engine, Microsoft Azure or AWS. There are many other providers.

Terminals and Shells


A terminal is a program that processes input from the keyboard and provides output, or feedback, from the operating system. The concept of a terminal harks back to the old days when large main-frame machines were accessed using standalone physical consoles; these consoles were referred to as computer terminals.

In Unix-like systems these days, the terminal is a program that opens allowing the user to type commands and read output.


From the GNU (Unix-like) OS documentation, "a shell is simply a macro processor that executes commands. The term macro processor means functionality where text and symbols are expanded to create larger expressions. A Unix shell is both a command interpreter and a programming language".

The shell is launched when a terminal is opened and the functionality of both the terminal and the shell provide access to the operating system.

Again, from the GNU OS documentation, "[s]hells may be used interactively or non-interactively. In interactive mode, they accept input typed from the keyboard. When executing non-interactively, shells execute commands read from a file".

Other programs, for example, Graphical User Interfaces (GUIs), that mediate between the user and the system are usually not called shells but are equivalent systems.

There are many Unix shells but the most common is called Bash. This is based on the original Bourne Shell. Bash is an acronym for "Bourne Again Shell".

The default prompt is a dollar sign followed by the Bash version number, e.g. bash-5.10$, or in the DCU environment, username@machine_name:~>

Apple moved its operating system default shell to Z Shell (zsh) from Bash a few years ago. Both MacOS and Linux are derived from Unix and so both inherited shells and the functionality is very similar. For much of the shell work, you can use zsh. Some things will be different, for example the .bashrc initialisation file doesn't exist in zsh; you'll find the .zshrc file instead. You can read about Apple's move to zsh here. However, you can enable Bash on Apple machines - you can find out how to do this here.

Shell Commands

As a note here, there is an accepted notation for describing commands. It is worth looking at some references, for example Google's note about document command-line syntax and reading the Bash documentation carefully. The output from Unix help files may be difficult to understand otherwise.


Shell commands are programs that allow you to control your machine and data effectively. Commands help with things like:

  • Automated software deployment.
  • Log analysis, retrieving text or strings.
  • Changing system configurations.
  • Performance monitoring.
  • File search and processing. As an example,
    $ mysqldump -u root -p '123456’ mydb > /tmp/mydb.backup
    $ gzip -9 /tmp/mydb.backup
    $ scp /tmp/mydb.backup username@remote_ip:/backup/mydb/

    These commands create a copy of a SQL, usually pronounced Sequel, database belonging to user "root" and upload it to a remote computer.

Some commands are built-in - called builtins and others can be installed later.

Interactive Mode

Shell commands can be input interactively at the prompt.

The shell has an associated current directory. This is the default starting point when locating files.

Commands are used by entering their names. As an example:

Typing ls and pressing Enter will run a program that lists the contents of the current directory. This sequence of actions is usually denoted,

$ ls

When you enter a command, the shell will check if the command is a builtin. If it's not, it will search its search path, i.e. all the directories that may contain the program. More about this later but the default directory for programs is the bin directory.


Flags are options that modify the behaviour of the command, e.g.

$ ls
Lists the files and directories (folders) in the current directory.

$ ls -l
Lists all information about the files and directories (folders) in the current directory. This is specified by the -l flag.

$ ls -al
Lists all files and directories (folders) in the current directory, including hidden files. This is specified by the -al flags.

The --help flag provides information about a command, e.g. ls --help.


Arguments are typed after the basic command and flags to further refine the command. They often refer to a file location. For example,

$ ls -l *.txt
In this case, the argument *.txt refines the list command to limit itself to all information about text files only in the current directory.

File and Folder Navigation

You can find out what folder you are currently in by using the pwd, or the print working directory, command:

$ pwd

cd means "change directory",

$ cd .
Change to the current working directory (.).

$ cd ..
Change to the directory above the current working directory (..).

ls ../../
List the contents of two directories above me.

$ cd ~
Change to the home directory (~). The home directory is the default base location for a user after logging in. A /home directory is created for each user on the system.

ls ~
List the contents of my home directory.

You can also use wildcards, e.g.

? matches a single character. For example, we could list myfil?.txt. This would return all files beginning with myfil and ending in .txt with any one character in between.

* matches all characters. For example, ls *.txt will list all text files in the current directory.

[] matches any one from a specified range of characters. For example, if a directory contains files called data.txt date.txt dats.txt, the command ls dat[ae].txt will return data.txt and date.txt.


Variables are created using <variable_name>=value, accessed using $<variable_name>.

By convention, variable names should be all uppercase. So VARIABLE_NAME, not variable_name.


Create a variable called NAME that stores your name. This line sets the variable:

$ NAME="Niall"

The echo command prints out the value, i.e.

$ echo $NAME

Note that the syntax is important. Accessing variables required an extra $ before the variable name.

Variable Syntax


When assigning a variable, you cannot have any spaces:

These are wrong:

$ NAME = Niall
$ NAME= Niall
$ NAME =Niall

This is right:

$ NAME=Niall

Quote Marks

You can define variables like this:

$ var=value
$ var='value'
$ var="value"

Quote marks are not needed on the right in Bash scripts although there are situations where you might use them.

Using Variables

You can use variables like this:

echo $var
echo ${var}

Read Only Variables

Variable values can be locked by setting the variable as "read only", so in the following example:

$ myName=Niall
$ readonly myName
$ myName="New Name"

We will get an error after the third line. We can't change a readonly value. You cannot reset a readonly variable.

However, you can always reset regular variables:

$ NAME=Niall
$ unset NAME
$ NAME="Mary"

Variables and Command Outputs

We can assign the results of commands to variables, so for example:

$ var=$(ls)
$ echo $var

You ought to see a list of files and folders in your directory.

The PATH Variable

When you type in a command, e.g. $ ls, shell checks if there is a function with that name (functions are user specified command groups), if not then if there is a builtin with that name and if not then if there exists an executable program in the locations specified by the PATH variable.

The PATH variable stores a list of possible directories and files.

When you enter a command, the PATH variable is checked. To see the locations specified in your PATH variable, type:

$ echo $PATH


Shell scripts can support one-dimensional arrays only, i.e. lists. For example, to create arrays, all with five things:

$ nums_1=(1 2 3 4 5)
$ nums_2=("A" "B" "C" "D" "E")
$ nums_3=(1 "B" 3 "4" "E")

You can easily add new terms, i.e. the length is flexible:

$ nums[6]="F"
$ nums[7]="G"

To get a particular element of an array:

$ ${array_name[index]}

To get the length of an array:

$ ${#array_name[@]}

To print all elements of an array requires a little scripting.

Shell Scripts

Hello World

Commands, variables and control flows are the building blocks of shell scripts

Create a file called using the touch command.

(The default usage of touch is to create or open and save a file without altering its contents. This has the effect of updating the file's access or modification date.)


$ touch

Use the Vi text editor to modify the file. Type:

$ vi

Type i to insert text. On the first line write,


This tells the operating system what interpreter to use, in this case Bash. sh is shorthand for the Bourne/Bash shell. Other possibilities include #!/usr/bin/python, i.e. Python. Press Enter. On the second line write,

echo Hello World

The contents of will look like this:

echo Hello World

Press Esc to escape out of the text editing mode and type :wq to write and quit the file.

The Vi/Vim Text Editor

The editor that we're using us vi, or visual editor. This is a standard text editor that is shipped with Unix/Linux systems that has been around since the 1970s. It was designed for writing C programs.

Vim, which stands for "vi improved", was an upgraded version of vi developed in the 1980s. In general, vim is shipped by default, so that in most Linux distributions, typing the vi will in fact launch vim.

Some distribution include a stripped down version of vim and you may need to manually upgrade if you want the full version.

In general, it's safer to type vim <filename> rather than vi <filename>.

Key Mappings

Vi uses the hjkl keys on the keyboard for navigation and the original implementation assigns letters to the arrow keys. Newer and more complete versions of vim have a more intuitive layout, with arrow keys working as you'd expect these days.

As an additional note, when you launch the program, you enter in "command" mode. To edit, you must type i for "insert" mode. If you get lost, hit esc to get back to "command" mode.

Saving Files

In this week's lecture, we created a file using touch example.txt. We then used vi example.txt to edit it.

You can also go straight to creating with vi by typing vi example.txt.

If you type vi with no argument, i.e. no filename, you will not be allowed save to disk. You must specify the file whe launching vi/vim.

You can find an overview of vi functionality in different places, including here (Colorado State), here (Indiana University).

There's a nice detailed history of vi/vim here.

Executable Scripts

You will need to make the script executable. When you create a file with touch, it is not executable by default. This is a feature of Unix-like operating systems. To make the file executable, use the chmod command:

$ chmod +x

Here the flag x makes the file executable. The filename is the argument. chmod is read as "change mode".

Running Scripts

To run the script, type:

$ ./

Note that the file location is explicitly defined using ./

Script Syntax

Pay attention to whitespace - the shell is sensitive to this. Whitespace errors are the most common cause of shell script bugs.

Comments are written as # My comment; the space after the # is important.

More About Variables

We can create and assign values to variables within shell scripts.


Create a script called The script will create a variable called NAME and assign it the value "Niall". The script will print out "Hello Niall" when it's run.

$ touch
$ chmod +x ./
$ vi

Script content:

echo $NAME


If you run a script with arguments, e.g.

$ ./ arg_one arg_two ...

The arguments will be passed into your script as variables. Within the script,

  • $0 is the name of the script.
  • $1 is the first argument.
  • $2 is the second.
  • Additional arguments follow the same syntax, i.e. $3, $4 and so on.
  • $@ refers to the entire list of arguments.
  • $# refers to the number of arguments passed.


Write a script called that prints out the first argument passed into it.

User Interaction

We can also as the user to input text by using the read command; in interactive mode, this is:

$ read myvar

$ read –p "prompt message" myvar
will first print out a message to the user.

Control will then be passed over to the user and wait for them to enter a value. In this example, the entered value is stored in a variable called myvar.


  • Create a file called
  • The script should first print out "What is your name? "
  • The user then enters a name.
  • The scripts prints out "Hello <name>".

If Statements

If statements begin with if and end with fi.

The syntax is, remembering the importance of spaces:

if [ condition ]; then
# run code

Comparing Strings

In order to compare two strings $a and $b, we can write a script containing:

if [ "$a" = "$b" ]; then
# This is a comment; the code goes here.

Remember spaces: "$a" = "$b" is different to "$a"="$b"

Comparing Integers

In order to compare two integers $a and $b, we use "–eq" instead of "=":

if [ "$a" -eq "$b" ]; then
# run code

String and Integer Comparison Operators

Equals= and ==-eq
Not equal!=-ne
Greater than (dictionary position for string)<-gt
Less than (dictionary position for string)<-lt
Greater than or equal-ge
Less than or equal-le
Is null (empty string)-z "string"
Is not null (not empty string)-n "string"

If / Else Statements

If/else control works as follows:

if [ condition ]; then
# run code
# run different code

As you'd expect.

Null Inputs

The read example above,, has a problem. The user does not have to enter a name at all and can return an empty value by pressing Enter. This result in a null string. This will cause problems!

The code [ -z "$var" ] checks if the variable var is empty or not.


Update the, script to make this fix using an if/else block. Make a new copy of and call it

Use the cp command to copy the file:
$ cp

Use Vi to edit the new file; update the script so that if the user enters an empty string it prints a warning message. Otherwise it ought to print out Hello <name> as before.

Else / If Statements

An else / if statement is written as elif. It works like this:

if [ condition ]; then
# run code
elif [ another_condition ]; then
# run this code instead
# run different code


Make a copy of the previously created file and call it

Change the code so that:

  • If there is no input at all, it prints an error message.
  • If the name entered is "Test", it print out "Everything is working fine."
  • Otherwise, it prints out the name entered.
  • Remember ["$a" = "$b"] checks if two strings are the same


Linux/Unix-like Systems The Linux kernel archive; the official Linux kernel website. Linux was written by Linus Torvalds.

Debian. The Debian free Linux distribution.

Linux on ChromeOS. Overview from Google.

Raspberry Pi OS. Overview.

MacOS Terminal User Guide. Apple.

Windows Subsystem for Linux.

Cygwin. Get that Linux feeling - on Windows.


Bash, the GNU Project's shell.

Bash. The official Bash reference manual. Most of your questions will have answers here.

Zsh. The default macOS shell.

Shell Commands and Useful References

Linux/BSD command line wizardry: Learn to think in sed, awk, and grep. Jim Salter at Ars Technica. This is a very nice overview of shell.

Command line wizardry, part two: Variables and loops in Bash. Part 2 of Jim Salter's nice review on Ars Technica.

Linux Essentials. Very complete "cheat sheet" put together by Thomas Girke at the University of California Riverside.

Linux Shell Commands. Another good summary page put together at Cardiff University's School of Computer Science & Informatics.

UNIX Introduction . Good overview from M. Stonebank in the University of Surrey.

MIT OpenCourseWare Notes on Operating System Engineering by Professor Kaashoek.

UNIX Commands. Summary Unix commands put together at North Carolina State University.

Gentoo's bash guide. Nice section about string and integer comparisons.

Google Developer Documentation Style Guide, Document Command-line Syntax. Useful overview of command notation syntax.