Lab #0: Virtual Linux Lab¶
Learn basic terminal commands and how to work with a text editor
Become familiar with the Linux environment
Learn to run a Python program from the command-line
Learn about file permissions
Learn about redirection and pipes
Linux is an operating system much like macOS or Windows. It has windows, programs, web browsers, and so on. Files are stored in directories (folders) that, in turn, are stored in other directories. Although you can access Linux’s features using your mouse, as you perform more and more complex tasks, you will find that using the mouse is ineffective. Linux allows us to interact with the computer entirely through text using a program called the terminal. (Mac provides a similar terminal application, and there are ways to use text-based commands on Windows too. But, Linux provides the lowest barrier to entry.) In this lab you will learn how to use the terminal to perform some basic operations in Linux. You will need these skills for the rest of your time at UChicago.
We show many examples of sample output below. The output you see when you run the commands may vary a bit.
Connecting to the Virtual Desktop¶
You will need to work through this lab by logging into a Virtual Desktop running Linux. We explain how to do this in our Virtual Desktop page. Make sure you complete the steps listed on that page before proceeding.
On your personal computer, you probably navigate your hard drive by double clicking on icons. While convenient for simple tasks, this approach is limited. For example, imagine that you want to delete all of the music files over 5 MB that you haven’t listened to in over a year. This task is very hard to do with the standard double-click interface but is relatively simple using the terminal.
On the virtual desktop, click the Application button (at the top left) and type “terminal” in the input box. Click the “terminal” icon to open the terminal window (we show screenshots of this in our Virtual Desktop page).
A terminal window will open and you will see text of the form:
username has been replaced by your CNetID and
is the name of the virtual desktop server you happen to be using. This
string is called the prompt. When you start typing, the characters
you type will appear to the right of the
The program that runs within a terminal window and processes the
commands the you type is called a shell. We use
bash, which is
the default shell on most Linux distributions, but there are other
popular shells, such as
The procedure for completing this lab is as follows. For each section, read through the explanatory text and the examples. Then, try these ideas by doing the exercises listed at the bottom of the section.
Using an Editor¶
List the files in the
lab0 directory. You should see the following:
my_echo.py hello_world.py test.txt
How do we view and edit the contents of these files? There are many high-quality text editors for Linux. We will use Visual Studio Code, which is good for writing code.
You can open a specific file, say
test.txt, using the
command from the Linux command-line by typing:
When you run this command, you will get a new window that looks like this:
Specifically, you’ll see the following text:
Lab 1 Test file =============== Author: Firstname Lastname
If the file is blank, quit
code and ensure that the file
test.txt exists in your local directory (use
ls to list the
files in your local directory). If it does not, use
cd to navigate
lab0 subdirectory inside your cmsc12100-aut-20-username`
Note: somewhat counterintuitively, the menu bar for Visual Studio Code is at the top of the Browser window. You need to run your mouse over the name to see the menu options.
For now, we will use Visual Studio Code (
code) in a very basic
way. You can navigate to a particular place in a file using the arrow
keys (or your mouse) and then type typical characters and delete them
as you would in a regular text editor. You can save your changes
save option in the file menu or use the keyboard
Crtl-s. To quit, you can use the file menu
option or the keyboard shortcut
As an aside, you can also launch
code from the application
launcher: simply click the Application button (at the top left of your
screen), type “code” in the input box, and then click on the Visual
Studio Code icon. You can then use the
file menu to navigate the
correct file. As with the terminal application, you might want to pin
the icon for launching Visual Studio Code to your launch bar (right
click your mouse and choose the “Lock to Launcher” menu item.)
Make sure that you are comfortable with this level of usage:
Add your name after
Author:in this file
Save the file
Close and reopen the file in
codeand ensuring that your name is still there
Run a Python Program¶
runs the python program file.py
In this class, you will learn Python. To run a Python program, use the
python3 and the name of the file that contains your program.
ls to verify that there there is a file named
hello_world.py in your
lab0 directory. Now, run the program in
hello_world.py by typing (don’t forget about auto-complete!):
This program is a very simple. It just prints “Hello, World!” to the screen.
There are several variants of Python, including Python 2.7 and
Python 3. We will be using Python 3 and the corresponding
python3 interpreter. The CS machines have Python 2.7
installed as the default Python. As a result, the command
python runs a version of Python 2.7. There are some
differences between the two languages and Python 3 programs may
not run properly using a Python 2.7 interpreter.
Edit and Run a Python Program¶
In this section you will modify and rerun the program in
hello_world.py. This change is very simple but goes through all
the mechanical steps needed to program.
Open the file
hello_world.py with the command:
The file contains a single line of code:
Change this line so that it instead says “Hello ” and then your name. For example if your name were Gustav Larsson, the line would read:
Do the following steps:
Save the file
hello_world.pyin Visual Studio Code (forgetting to save is a surprisingly common error)
Rerun the program using
Let’s reinforce the steps to programming in Python with the terminal:
.pyfile with an editor
Save the file
Run the file with
Forgetting to save the file (step 2) is a very common mistake!
Wild Cards (using an asterisk)¶
Sometimes when we enter a string, we want part of it to be variable, or a wildcard. A common task is to list all files that end with a given extension, such as
.txt. The wildcard functionality, through an asterisk, allows to simply say:
$ ls *.txt
The wildcard can represent a string of any length consisting of any characters - including the empty string.
It is important to be careful using wildcard, especially for commands like
rm which cannot be undone. A command like:
$ rm * ### DO NOT RUN THIS COMMAND!
will delete all of the files in your working directory!
Navigate to your
cmsc12100-aut-20-usernamedirectory. What do you see when you run
ls lab*? What about
What do you expect to see when you run the command
ls ../lab*from within your
Useful Keyboard Shortcuts¶
Used at the Linux prompt, the keyboard shortcut
Ctrl-P will roll
back to the previous command. If you type
Ctrl-P twice, you will
roll back by two commands. If you type
Ctrl-P too many times, you
Ctrl-N to move forward. You can also use the arrow keys:
up for previous (backward), down for next (forward).
Here are few more useful shortcuts:
Ctrl-Awill move you to the beginning of a line.
Ctrl-Ewill move you to the end of a line.
Ctrl-Uwill erase everything from where you are in a line back to the beginning.
Ctrl-Kwill erase everything from where you are to the end of the line.
Ctrl-Lwill clear the text from current terminal
Play around with these commands. Being able to scroll back to, edit, and then rerun previously used commands saves time and typing! And like auto-completion, getting in the habit of using keyboard shortcuts will reduce frustration as well save time.
A man page (short for manual page) documents or describes topics applicable to Linux programming. These topics include Linux programs, certain programming functions, standards, and conventions, and abstract concepts.
To get the man page for a Linux command, you can type:
man <command name>
So in order to get the man page for
ls, you would type:
This command displays a man page that gives information on the
ls command, including a description, flags, instructions on use, and other information.
Each man page has a description. The
-k flag for
man allows you to search these descriptions using a keyword. For example:
man -k printf
This searches all the descriptions for the keyword
printf and prints the names of the man pages with matches.
Running Commands Sequentially¶
It is often convenient to chain together commands that you want to run in sequence. For example, recall that to print the working directory and list all of the files and directories contained inside, you would use the following commands:
$ pwd /home/username/ $ ls Desktop Documents Downloads Music Pictures Public Templates Videos
You could also run them together, like so:
$ pwd ; ls /home/username/ Desktop Documents Downloads Music Pictures Public Templates Videos
pwd is executed and run to completion, and then
ls is executed and
run to completion. The two examples above are thus equivalent, but the ability to
run multiple commands together is a small convenience that could save you some time
if there is a group of commands that you want to execute sequentially.
The shell doesn’t care about white space, so it will run any of the following as well:
$ pwd;ls $ pwd ;ls $ pwd; ls $ pwd ; ls
The examples in this section will use commands that we’ve not yet discussed. Refer to the man pages for information about unfamiliar commands.
As we already know, commands like
print output to screen by default. Sometimes, however, we may prefer
to write the output of these commands to a file. In Linux, we can
redirect the output of a program to a file of our choosing. This
operation is done with the
Try the following example and compare your output with ours:
$ cd $ touch test-0.txt $ ls > test-1.txt $ cat test-1.txt Desktop Documents Downloads Music Pictures Public Templates test-0.txt test-1.txt Videos $ echo "Hello World!" > test-2.txt $ cat test-2.txt Hello World! $ cat test-2.txt > test-1.txt; cat test-1.txt Hello World! $ rm test-*
Two important things to note:
If you redirect to a file that does not exist, that file will be created.
If you redirect to a file that already exists, the contents of that file will be overwritten.
You can use the append operator (
>>) to append the output of
command to the end of an existing file rather than overwrite the
contents of that file.
Not only can we redirect the output of a program to a file, we can
also have a program receive its input from a file. This operation is
done with the
< operator. For example:
$ python3 my_echo.py < my-input.txt
(Change back to your
lab0 directory before you try this command.)
In general, all Linux processes can perform input/output operations
through, at least, the keyboard and the screen. More specifically,
there are three ‘input/output streams’: standard input (or
standard output (or
stdout), and standard error (or
The code in
my_echo.py simply reads information from
writes it back out to
stdout. The redirection operators change
the bindings of these streams from the keyboard and/or screen to files.
stderr later in the term.
In addition to the ability to direct output to and receive input from files, Linux provides a very powerful capability called piping. Piping allows one program to receive as input the output of another program, like so:
$ program1 | program2
In this example, the output of program1 is used as the input of
program2. Or to put it more technically, the
program1 is connected to the
As another more concrete example, consider the
man command with the
-k option that we’ve
previously discussed. Let’s assume that you hadn’t yet been introduced to the
How would you look for the command to create a directory? First attempts:
$ man -k "create directory" create directory: nothing appropriate $ man -k "directory" (a bunch of mostly irrelevant output)
As we can see, neither of these options is particularly helpful. However, with
piping, we can combine
man -k with a powerful command line utility called
grep (see man pages) to find what we need:
$ man -k "directory" | grep "create" mkdir (2) - create a directory mkdirat (2) - create a directory mkdtemp (3) - create a unique temporary directory mkfontdir (1) - create an index of X font files in a directory mklost+found (8) - create a lost+found directory on a mounted Linux second extended fil... mktemp (1) - create a temporary file or directory pam_mkhomedir (8) - PAM module to create users home directory update-info-dir (8) - update or create index file from all installed info files in directory vgmknodes (8) - recreate volume group directory and logical volume special files
Use piping to chain together the
tailcommands to display the last 10 lines of output from
Replicate the above functionality without using the
|operator. (hint: Use a temporary file.)
Sometimes we want to restrict who can access certain resources on the file system.
Most file systems assign ‘File Permissions’ (or just permissions) to specific users and groups of users. Unix is no different. File permissions dictate who can read (view), write (create/edit), and execute (run) files on a file system.
All directories and files are owned by a user. Each user can be a member of one or more groups. To see your groups, enter the command
groups into the command line.
File permissions in Unix systems are managed in three distinct scopes. Each scope has a distinct set of permissions.
User - The owner of a file or directory makes up the user scope.
Group - Each file and directory has a group assigned to it. The members of this group make up the group scope.
Others - Every user who does not fall into the previous two scopes make up the others scope.
If a user falls into more than one of these scopes, their effective permissions are determined based on the first scope the user falls within in the order of user, group, and others.
Each scope has three specific permissions for each file or directory:
read - The read permission allows a user to view a file’s contents. When set for a directory, this permission allows a user to view the names of files in the directory, but no further information about the files in the directory.
r is shorthand for read permissions.
write - The write permission allows a user to modify the contents of a file. When set for a directory, this permission allows a user to create, delete, or rename files.
w is shorthand for write permissions.
execute - The execute permission allows a user to execute a file (or program) using the operating system. When set for a directory, this permission allows a user to access file contents and other information about files within the directory (given that the user has the proper permissions to access the file). The execute permission does not allow the user to list the files inside the directory unless the read permission is also set.
x is shorthand for execute permissions.
To list information about a file, including its permissions, type:
ls -l <filepath>
You’ll get output of the form:
<permissions> 1 owner group <size in bytes> <date modified> <filepath>
For example, if we want information on
$ ls -l /usr/bin/python3.5 -rwxr-xr-x 1 root root 4460272 Aug 20 /usr/bin/python3.5
First thing we can notice is that the owner of the file is a user
root is a name for an account that has access
to all commands and files on a Linux system. Other accounts may
also have “root” privileges.) The file’s group is also
The permissions are
-rwxr-xr-x. The initial dash (
/usr/bin/python3.5 is a file, not a directory.
Directories have a
d instead of a dash. Then the permissions are
listed in user, group, and others order. In this example, the owner,
root, can read (
r), write (
w), and execute (
file. Users in the
root group and all other users can read and
execute the files.
By default, any files or directories that you create will have your
username as both the user and the group. (If you run
you’ll notice that there is a group with the same name as your
username. You are the only member of this group.) On our Linux
machines, by default, new files are give read and write
permissions to user and group and no permissions to other. New
directories will be set to have read, write and execute permissions
for user and group.
Verify this claim by running
ls -l backups/copy2.txtand
ls -ld backupsin your
-d flag tells
ls to list the directory, instead of its
contents. Notice that that the first letter in the permissions string
backups is a d, while it is a
Once you have verified the claim, go ahead and remove the
directory using the command:
rm -r backups.
Changing Permissions, Owner, & Group¶
set the permissions for a file/directory
update the permissions for a file/directory
change the owner of a file to username
change the group of a file
print the contents of a file to the terminal
To change permissions, we use the
chmod command. There are two
ways to specify the permissions. We’ll describe the more accessible
one first: to set the permissions you specify the scope using a
o, the permission using
x, and either
- to indicate that you want
to add or remove a permission. For example
uo+rw indicates that
you want to add read and write permissions for the user and others
We can demonstrate this using the
cat command to print file
contents to the terminal:
$ echo "Hello!" > testfile $ ls -l testfile -rw-rw---- 1 username username 7 Aug 23 11:22 testfile $ cat testfile Hello! $ chmod ug-r testfile #remove read and permissions from user and group $ ls -l testfile --w--w---- 1 username username 7 Aug 23 11:22 testfile $ cat testfile cat: testfile: Permission denied $ chmod u+r testfile #give user scope read permissions
In this last example, we have added user read permissions to
In addition to the symbolic method for setting permissions, you can also use a numeric method: each permission has a unique value: read = 4, write = 2, execute = 1. As a result, you can describe the permissions of each scope using the sum of its permissions’ values. For example, if a file has read and write permissions for the user scope, its permissions can be described as 6 (4 + 2 = 6).
You can describe the permissions of a file overall using these values for each scope. For example, 761 describes the permissions for a file with read, write, and execute permissions for the user scope, read and write permissions for the group scope, and only execute permissions for the others scope.
The symbolic approach is relative: it allows you to add and remove permissions relative the the current file permissions. The numeric method is absolute: it sets the permissions to a specific configuration. We recommend starting the symbolic approach. It is easier to get right. As you get more comfortable with setting permissions, it is useful to learn how to use the numeric method.
To change the owner of a file or directory (if you are the owner or root), use the command:
chown <new owner> <path to file>
To change a file’s group (if you are the owner or root), use the command:
chgrp <new group> <path to file>
It is unlikely that you will need to use these two commands for this course.
echo "Hello!" > testfileto construct
testfile. Look at the permissions using
Change the permissions on
testfileto allow and read access for others. Run
ls -l testfileto check the new permissions.
Remove group write access from
testfile. Check the corrected permissions.
Sometimes, a program will run indefinitely or misbehave. When this
happens, you can type
Ctrl-C to send an interrupt signal to the
running program, which usually causes it to terminate. On occasion,
you may need to type
Ctrl-C a few times. Typing
an end of input signal, which tells the program that no more
information is coming.