The engineering servers run a Debian-based Linux distribution, so once you're logged into the engineering servers, you can proceed to execute any shell commands that work in your default Linux shell. We'll be using the Bourne Again Shell (Bash), but most of the shell commands that we'll be using are actually system-installed programs that are standard on every Linux system and work with all Linux shells. Still, for consistency, if you haven't already, you should configure your user account on the engineering servers to use Bash by default. You can do this via TEACH.
A shell can be thought of as an advanced, text-based version of a file explorer. When you open up the Windows file explorer or Mac Finder (etc), you're presented with a bunch of files and folders. When you click (or double-click) on a file, it opens that file in the default application configured for that kind of file. When you click (or double-click) on a folder, it navigates into that folder so that you can see the other files and folders contained inside it.
A shell is very similar, except it's text-based, meaning that there are no icons to click on—there's only text, which is displayed when you execute certain shell commands. At any given point in time, your shell is operating inside a certain folder. Folders are often referred to as directories, and the folder (directory) that your shell is currently operating inside is referred to as the working directory. To display the contents of your working directory (i.e., to see the files and folders contained inside your current folder), execute the ls shell command. For example, this is what it looks like when I execute ls immediately after logging into the engineering servers:
(base) guyera@flip1:~$ ls
bin instructor perl5 sc2_rl_code.tar.gz Windows.Documents
envs lib public_html share
guille miniconda3 samples tamarisk-gen-code.tgz
include openssl saves trash
On Unix-like systems (which includes Linux and therefore the engineering servers), any file whose name starts with a . is said to be a hidden file. By default, ls will only show you non-hidden files. To see hidden files, execute ls -a:
(base) guyera@flip4:~$ ls -a
. .esd_auth .logout .ssh
.. .forward .mailrc .systemtap
.bash_history .ghc .matplotlib tamarisk-gen-code.tgz
.bash_profile .gitconfig miniconda3 .tcshrc
.bashrc .gsutil .mongorc.js test.txt
.bashrc.bak.0 guille .netrc .tmux.conf
.bashrc-conda .history .node_repl_history trash
bin .idlerc .npm .vim
.cache include .nv .viminfo
.ccache instructor openssl .vimrc
.conda .ipython perl5 .wget-hsts
.config .jupyter .pki Windows.Documents
.cshrc .keras public_html .Xauthority
.cshrc.bak.0 .lesshst .python_history .xonshrc
.dbshell lib samples .zshrc
.emacs.d .lmod.d saves
.env .local sc2_rl_code.tar.gz
envs .login share
To see what your current working directory is, execute the pwd shell command:
(base) guyera@flip1:~$ pwd
/nfs/stak/users/guyeraMy working directory is currently /nfs/stak/users/guyera. Indeed, when you first log into the engineering servers, your working directory will be your home directory by default. My home directory is /nfs/stak/users/guyera. Every user has their own home directory. Yours will be similar, except my ONID will be replaced with yours.
/nfs/stak/users/guyera is referred to as an absolute path. Absolute paths are one of two kinds of file paths. File paths specify the location of a file or directory within a file system. Absolute paths start with a /, and they specify the entire location of the file or directory relative to the "top", or "root", of the file system. That's to say, /nfs/stak/users/guyera refers to a directory named guyera, which is inside another directory named users, which is inside another directory named stak, which is inside another directory named nfs, which is inside the root directory (i.e., the "top-level" directory) of the entire file system (the root directory doesn't really have a name, but you can think of it as being named / if that makes sense to you).
Of course, there are shell commands that allow you to change your working directory (i.e., navigate the file system). But before we can do that, let's first create a new directory to navigate into. You can do this with the mkdir shell command. This command is slightly more complicated than ls or pwd in that you must provide it a command-line argument. Command-line arguments are simply additional inputs to shell commands. To provide command-line arguments to a shell command, simply type them out after the name of the command itself, separated by spaces, before pressing the enter key to execute the command. In the case of mkdir, we must provide a single command-line argument specifying the path of the directory that we want to create. Let's create a directory named cs162 inside our home directory. Execute the following command, replacing my ONID with yours:
mkdir /nfs/stak/users/guyera/cs162The above command creates a directory named cs162 inside the directory named guyera (my home directory), which is inside the directory named users, and so on. If you execute ls again, you should be able to see the newly created cs162 directory:
(base) guyera@flip1:~$ ls
bin include openssl saves trash
cs162 instructor perl5 sc2_rl_code.tar.gz Windows.Documents
envs lib public_html share
guille miniconda3 samples tamarisk-gen-code.tgz
Before we move on, I should tell you about relative paths. I said that absolute paths are one of two kinds of file paths. Relative paths are the other kind. A relative path is any file path that does not start with a /, and it specifies the location of a file or directory relative to your current working directory. For example, /nfs is an absolute path (it starts with a /), and it specifies a file or directory named nfs, which is inside the root directory of the file system. In contrast, nfs (without the / at the beginning) is a relative path, and it specifies a file or directory named nfs, which is inside your current working directory. In most contexts where you need to specify a file path, you can specify either an absolute path or a relative path. For example, when we executed the previous shell command to create the cs162 directory inside our working directory, we could have instead specified a relative path, and it would have done the exact same thing. In that particular case, a relative path would have been much easier to type out. It would've looked like this:
mkdir cs162Okay, let's move on. Suppose you want to change your working directory. In other words, you want to move from one directory to another. In a file explorer, you'd usually do this by clicking (or double-clicking) on the folder that you want to navigate into. But again, terminals and shells are text-based interfaces; barring certain exceptions, the mouse is mostly useless in a terminal, and there aren't even any folder icons to click on to begin with. Instead, you must use another shell command: cd. The cd command also accepts a single command-line argument, specifying the path of the directory that you want to navigate into (which will then become your working directory). This path can either be an absolute path or a relative path. Let's navigate into the cs162 directory that we created previously. It's inside our home directory, which is also our current working directory, so let's use a relative path:
cd cs162To prove that it worked, execute pwd again, and you'll see that your working directory has changed:
(base) guyera@flip1:cs162$ pwd
/nfs/stak/users/guyera/cs162Since we're creating directories, let's create some more to help you organize your work for this class. Inside your cs162 directory (which is currently your working directory), create an assignments directory and a labs directory:
mkdir assignments
mkdir labsFor the sake of demonstration, navigate into your newly created assignments directory:
cd assignmentsWe're now inside our assignments directory, which is inside our cs162 directory. Suppose we want to navigate back "up" into our cs162 directory. To do that, simply execute cd with .. as the command-line argument:
cd .... is a special alias, or "nickname", for a given directory's parent. The parent of a directory is simply the directory that contains it. Hence, .. can be thought of as a relative path that specifies the parent directory of the current working directory (i.e., the directory that contains the current working directory). Our working directory was the assignments directory, and its parent is cs162, so cd .. navigated us "up" into the cs162 directory.
Just as .. is an alias for a given directory's parent, . (just a single period) is an alias for a directory itself. Hence, by itself, . can be thought of as a relative path that simply specifies the current working directory. This is helpful when you want to specify the current working directory as a command-line argument to a shell command. You may see some examples of this later when we discuss more advanced shell commands.
There's another way to use the cd command: if you execute it without specifying any command-line arguments, it will automatically navigate you all the way back to your home directory (in my case, /nfs/stak/users/guyera), regardless of what your current working directory is. In other words, to get back to your home directory at any time, simply execute:
cdYou now know how to organize and navigate your file space on the engineering servers using pwd, ls, cd, and mkdir, but terminals and shells are capable of a lot more than that. Below are some other shell commands that you might find useful every now and then.
rm: used to remove (delete) files. Provide a single command-line argument specifying the path to the file you want to remove. For example, the following shell command would delete the file called hello.txt that's currently in your working directory (assuming such a file exists):
rm hello.txtrm -r: used to remove (delete) directories, including everything inside them. It's technically the same command as the previous one, but with an additional -r command-line argument. This is a special command-line argument known as a flag. Flags simply enable special capabilities of shell commands that would otherwise be disabled. By default, rm is not capable of removing entire directories. But when the -r flag is provided, it can. For example, the following shell command would delete the directory called images that's currently in your working directory (assuming the images directory exists):
rm -r imagescp: used to create copies of files. Provide two command-line arguments: the path of the existing file that you want to create a copy of, and the path that you want the new copy to have. For example, the following shell command would copy the file called hello.txt that's currently in your working directory, and the copy would be called goodbye.txt (also in your working directory):
cp hello.txt goodbye.txtcp -r: used to create copies of entire directories, including everything inside them. It works exactly like cp. The -r flag simply enables copying directories. For example, the below shell command would copy the directory called images that's currently in your working directory, and the copy would be called backup (also in your working directory). The contents of the two directories would be identical—all of the files and directories within the images directory are copied along with it.
cp -r images picturescat: used to display the contents of a file in the terminal. Provide a single command-line argument, specifying the path of the file whose contents you want to display. For example, the following shell command would display the contents of the file called hello.txt in your working directory (assuming such a file exists):
cat hello.txtcat can also be used to concatenate two or more files' contents together into a single string of text (this was actually its original purpose), but it's mostly just used to display file contents in the terminal. It will be more useful once we've discussed terminal-based text-editing.
Being able to use a terminal and shell efficiently will make your life a lot easier. Here are some simple tricks to speed things up.
Pressing the up arrow on your keyboard will iterate backward through your history of recently executed shell commands (and pressing the down arrow will iterate forward through it). For example, at any given time, simply pressing the up arrow followed by the enter key will usually re-execute whatever shell command you executed most recently.
Typing an exclamation point followed by a few characters and pressing enter will re-execute whatever command you most recently executed starting with those characters. For example, if you recently executed cat coolfile.txt, then typing !ca and pressing enter will re-execute that same command (assuming you haven't executed any other commands starting with ca even more recently).
The history command (which accepts no command-line arguments) prints your history of recent shell commands.
When typing out a file path as a command-line argument to a shell command, you can press the tab key to autocomplete parts of the path. For example, if you're trying to remove the file called long-file-name-that-nobody-wants-to-type.txt (e.g., with the rm shell command), rather than typing out the entire file name, you can just type out the first couple of letters and press the tab key. Your terminal will autocomplete as much as it can. If you press the tab key and find that it only autocompletes part of the file name, one possible reason is that you simply mistyped the first few characters, but the other possibility is that there are multiple files in the directory that starts with the same few characters. In the latter case, pressing the tab key will only autocomplete up until the point where the two file names differ. At that point, pressing the tab key twice in rapid succession will print out the names of all of the files starting with those characters.
Holding Ctrl and pressing C will terminate (immediately end) whatever command is currently executing. However, it can also be used to effectively cancel whatever command you have typed out so far. For example, suppose you start typing out a really long command only to realize that you made a mistake at the very beginning of it, or perhaps you change your mind and decide that you don't want to execute the command at all. In either case, you can simply hold Ctrl and press C, and it will cancel everything that you've typed so far.