ModernCS
Session 1.190 minFree preview

The Shell and the Filesystem

Move around a Linux machine, read and edit files, and stop fearing the terminal.

By the end of this session you will be able to:

  • State exactly where you are in a Linux filesystem and move anywhere else in it using both absolute and relative paths
  • Read any text file on the machine and pull one line out of a large one, without opening an editor
  • Edit a file you own and a file you do not, and read the permission bits that decide which is which

Everything else in this course runs on a Linux machine. Docker builds on it, Kubernetes schedules onto it, your cloud instance boots it. If you cannot answer "where am I and what is in this directory" without guessing, every later error message will look like magic.

Use Ubuntu 26.04 LTS as your reference machine. A virtual machine, WSL on Windows, or a cheap VPS all behave the same for this session.

Where you are is a real thing

The shell prints a prompt and waits. Every command you type runs relative to one directory, your current working directory, and the single most common beginner failure is running a correct command in the wrong place. So ask first:

pwd

That prints something like /home/student. Now look around:

ls
ls -l
ls -la

Plain ls gives you names. -l gives the long form: permissions, owner, group, size in bytes, modification time. -a adds entries starting with a dot, which the shell hides by default. Configuration lives in those dotfiles, so ls -la is the version you actually want on a server.

Moving is cd, and it takes two kinds of path. An absolute path starts with / and means the same thing from anywhere. A relative path does not, and means "from here":

cd /etc
pwd
cd ..
pwd
cd ~
cd -

.. is the parent directory, . is the current one, ~ is your home directory, and cd - jumps back to where you just were. cd with no argument goes home.

Now the habit that saves you the most time: press Tab. Type cd /et, hit Tab, and the shell completes it. Hit Tab twice on an ambiguous prefix and it lists the candidates. If Tab does not complete, what you are typing does not exist, and you found your typo before running the command instead of after.

One tree, starting at /

Windows gives you C: and D: as separate roots. Linux has exactly one root, /, and everything hangs off it, including extra disks, which get attached at some directory inside the tree. There is no second tree to get lost in.

Six directories carry most of what you care about:

  • /etc is configuration, almost all of it plain text you can read
  • /var is data that changes while the machine runs, including /var/log
  • /home/yourname is your own files, and the only place you can write without asking
  • /usr/bin and /usr/local/bin hold the programs the shell runs
  • /tmp is scratch space that gets cleared
  • /opt is where hand-installed third party software tends to land

That last one matters in two sessions, when you install an app by hand and write down where its files went.

The shell finds programs by searching a list of directories in order. Print that list, then find where one program actually lives:

echo $PATH
command -v ssh

"Command not found" rarely means the program is missing. It usually means the program is not in one of those directories.

Reading a file is not editing it

Opening an editor to read a file is how files get changed by accident. Read them with tools that cannot write.

cat /etc/os-release

cat dumps the whole file to your screen, which is right for short files:

PRETTY_NAME="Ubuntu 26.04 LTS"
NAME="Ubuntu"
VERSION_ID="26.04"
VERSION="26.04 LTS (Resolute Raccoon)"
ID=ubuntu

For anything long, use less, which pages instead of flooding your terminal:

less /etc/services

Inside less: Space moves down a page, b moves back, / searches, n jumps to the next match, and q quits. Learn q now. Being stuck in a pager with no visible way out is a common reason people give up on the terminal.

When you only want the top or the bottom:

head -n 5 /etc/passwd
tail -n 5 /etc/passwd

And when you want one line out of thousands, or one line out of a whole directory tree, use grep:

grep -n "^root" /etc/passwd
grep -rn "$USER" /etc 2>/dev/null

-n prints line numbers, -r searches recursively, and -i ignores case. The 2>/dev/null throws away the permission errors from files you are not allowed to read, so the real matches are not buried. That is the difference between "the config is somewhere in /etc" and knowing the file and the line number.

Editing, and the bit that says no

Look at the long listing again and read it properly:

-rw-r--r-- 1 root root 221 Apr 23 09:12 /etc/hosts

The first character is the type: - for a regular file, d for a directory, l for a symbolic link. The next nine are three groups of three: what the owner can do, what the group can do, and what everyone else can do, each as read, write, execute. So rw-r--r-- owned by root means root changes it and you only read it.

That is why editing your own file just works:

nano ~/notes.txt

In nano, ^O in the help bar means Ctrl and O. Ctrl+O then Enter saves, Ctrl+X exits. Editing a root-owned file needs sudo:

sudo nano /etc/hosts

sudo runs one command as the administrator. It is not a general fix for a command that failed: if the reason was a wrong path or a typo, sudo just fails as root.

The execute bit is the one people trip over. Make a script and watch it:

printf '#!/bin/bash\necho hello from a script\n' > ~/hello.sh
bash ~/hello.sh
~/hello.sh
chmod u+x ~/hello.sh
~/hello.sh

bash ~/hello.sh works immediately, because you are running bash and handing it a file to read. ~/hello.sh fails until chmod u+x adds execute permission for the owner, because then you are asking the kernel to run the file itself.

Try it

On your Linux machine, starting from your home directory:

mkdir -p ~/webcraft/notes
cd ~/webcraft/notes
cp /etc/os-release distro.txt
grep -n "VERSION=" distro.txt

Then run nano notes.md and write three lines: the version string you just grepped, the absolute path of the directory you are in, and one command from this session you had to look up. Save with Ctrl+O and Enter, exit with Ctrl+X.

Success condition: from any directory on the machine, ls -l ~/webcraft/notes lists both distro.txt and notes.md with your username in the owner column, and cat ~/webcraft/notes/notes.md prints your three lines. If you needed sudo at any point, you were writing in the wrong directory.

Common mistakes

  • Typing paths by hand instead of pressing Tab. Half of all "no such file or directory" errors are typos in a path Tab would have completed correctly, and Tab confirms the thing exists before you commit.
  • Reaching for sudo the moment a command fails. Read the error first. "Permission denied" is a job for sudo. "No such file or directory" is a job for pwd and ls, and running it as root changes nothing except the damage a typo can do.
  • Using cat on a large file. It scrolls past faster than you can read and pushes everything useful out of your scrollback. Use less to browse, head or tail for the ends, grep when you know what you are looking for.
  • Copying unusual flags off a blog post. Ubuntu has been replacing the classic GNU versions of these commands with a Rust reimplementation, starting in 25.10, and obscure flags are exactly where two implementations differ. The standard flags here work on either. When unsure, man ls on the machine in front of you beats a search result.

Where this goes next

The next session, Processes, Ports, and Logs, turns the same skills on a running machine: which programs are actually running, which port each one listens on, and what it wrote into a file under /var/log. You already know how to find and read that file, which is most of the work.

That was one session of 3 in this phase.

DevOps & Cloud runs to 5 phases. Buy the whole course, or just the phase you need.