You have your snapshot taken and a session open on srv-tramontana. In front of you there is a blinking prompt and little else. That screen, which at first sight looks like a limitation, is in fact the most powerful interface the system has: everything that can be done on a Linux server can be done from there, and almost nothing done there is unrepeatable.

This lesson is not a list of commands. It is the lesson where you learn how the interpreter between your fingers and the kernel works: how it reads what you type, how it decides which program to run, how you can type three times faster by using the keyboard properly, and how to chain commands so that one depends on the result of the previous one. From here on, every new command you learn will rest on this mechanism.

By the end you should be able to sit down at any Linux terminal and move without friction: without deleting a whole line by holding down backspace, without retyping a command you already ran ten minutes ago, and without a space in a file name ruining your instruction.

Contents

  1. Why the command line is still the professional tool
  2. The REPL cycle: what the shell does with what you type
  3. Anatomy of a command: command, options and arguments
  4. Internal and external commands: builtins, type, which and command -v
  5. How the shell finds an executable
  6. Tab completion
  7. The command history
  8. Editing the command line without suffering
  9. Chaining commands: ;, &&, || and grouping
  10. Running in the background with &
  11. Quoting and escaping: when the name has spaces
  12. Cancelling and exiting

  1. Why the command line is still the professional tool

The question is a fair one: in 2026, with mature graphical interfaces and web administration panels, why does a professional work in a terminal?

The answer is not nostalgia. It is four properties the graphical interface cannot offer:

  • Reproducibility. A command is text. It can be copied, pasted, saved in a document, checked in a code review and run identically six months later. "Click on Settings, then on the Advanced tab, then tick the third box" is not reproducible: it depends on the version, on the language and on the box still being there.
  • Automation. What you type by hand today is literally the first line of the script that will do it on its own tomorrow. Between running a command and automating it there is no translation step: it is the same text. In a graphical interface, automating means rewriting the whole process in another language.
  • Remote work. srv-tramontana has no monitor and never will. When the server is in a data centre or in a cloud, your only door will be SSH. The CLI is designed for that; remote desktop is a patch.
  • Cost in resources and bandwidth. An SSH session consumes a few kilobytes per minute and works over a poor mobile connection from a train. A remote desktop needs megabits and drops out. When you have an incident at three in the morning from your phone, this will stop being a technical detail.

Now the honest part, because the CLI does not win at everything:

Criterion Graphical interface (GUI) Command line (CLI)
Learning curve Gentle: the options are visible Steep: you have to know they exist
Discoverability High: you explore menus Low: you need documentation (lesson 02-02)
Speed for the expert Limited by the mouse Very high
Reproducibility Low Total
Automation Difficult or impossible Native
Remote work Heavy, fragile Light, robust
Visual tasks (images, design, diagrams) Irreplaceable Unsuitable
Resource consumption High Minimal
Margin for destructive error Low: it confirms and warns High: it runs and says nothing

That last point deserves a pause. The Unix philosophy you saw in Module 1 includes an implicit rule: silence is a sign of success. If a command works, it usually says nothing. And if you ask it to delete a directory tree, it deletes it without asking. The power and the danger are the same property seen from two sides.

The professional conclusion is not "the CLI is better", but: for administering systems, the CLI is the right tool, and not mastering it limits you to doing by hand what others automate.

  1. The REPL cycle: what the shell does with what you type

Bash does not run what you type. It runs the result of processing what you type. Understanding that difference will save you a lot of surprises.

The shell works in a loop called the REPL (Read–Eval–Print–Loop): it reads, evaluates, prints and starts again.

flowchart TD
    A[Show the prompt] --> B[READ: wait for a complete line]
    B --> C[SPLIT: break into words by spaces]
    C --> D[EXPAND: wildcards, variables, substitutions, ~]
    D --> E[RESOLVE: is it a builtin, an alias or an external program?]
    E --> F[EXECUTE: launch the process and wait]
    F --> G[PRINT: standard output and errors on screen]
    G --> H[STORE: exit code in $? and history]
    H --> A

Notice the EXPAND step: it happens before anything is run. When you type a command with a *, the program never sees the asterisk; it sees the list of names the shell has put in its place. Wildcards and variables are covered in Module 3, but it is worth knowing now that this intermediate phase exists, because it explains behaviours that otherwise look like magic.

And notice SPLIT: the shell divides the line by spaces before knowing what they mean. That detail is the cause of the quoting problem you will see in section 11.

  1. Anatomy of a command: command, options and arguments

You already saw the general shape in Module 1. Now we take it apart completely:

command [options] [arguments]
  • Command: what you want to do. Always the first word.
  • Options (or flags, switches): how you want to do it. They start with - or --.
  • Arguments (or operands): what you want to do it to. Usually files or paths.
operator@srv-tramontana:~$ ls -l -h /var/log/tramontana
total 32K
-rw-r----- 1 root adm  18K Aug 18 09:14 access.log
-rw-r----- 1 root adm 6.2K Aug 18 09:02 errors.log

Here ls is the command, -l and -h are options and /var/log/tramontana is the argument. Without an argument, ls uses a default value (the current directory); without options, it uses its default behaviour.

Short, long and value-taking options

Form Example Notes
Short -l One letter, one hyphen. Case matters: -r and -R are usually different things
Short, grouped -lh = -l -h Only those that take no value can be grouped
Long --human-readable Two hyphens, a whole word. More readable in scripts
Short with a value -n 5 or -n5 The space is usually optional, but not always
Long with a value --lines=5 or --lines 5 With = it is the safest form

The following three invocations are equivalent:

ls -l -a -h /etc
ls -lah /etc
ls --format=long --all --human-readable /etc

Professional criterion: use short options when typing by hand (speed) and long ones when writing a script or documenting a procedure (readability). Six months from now, --human-readable explains itself; -h forces you to look at the manual. And beware: -h does not mean the same thing in every command.

The -- separator

A bare -- means "no more options; everything that follows is an argument, even if it starts with a hyphen".

operator@srv-tramontana:~$ touch -- -report.txt
operator@srv-tramontana:~$ ls
-report.txt

operator@srv-tramontana:~$ rm -report.txt
rm: invalid option -- 'e'
Try 'rm ./-report.txt' to remove the file '-report.txt'.

operator@srv-tramontana:~$ rm -- -report.txt

Without --, rm interprets -report.txt as a pile of separate options. It is a rare case when typing by hand, but it stops being rare when a script receives file names from outside: any name starting with a hyphen can alter the command's behaviour. That is why serious scripts (Module 4) use -- before the data.

  1. Internal and external commands: builtins, type, which and command -v

Not every command is a program. There are two categories:

  • Builtins (internal): Bash implements them. There is no file to run; the shell does the work itself. They are extremely fast.
  • External: they are executables on disk (/bin/ls, /usr/bin/find...). The shell creates a new process to run them.

The tool for telling them apart is type:

operator@srv-tramontana:~$ type cd
cd is a shell builtin

operator@srv-tramontana:~$ type ls
ls is aliased to `ls --color=auto'

operator@srv-tramontana:~$ type -a ls
ls is aliased to `ls --color=auto'
ls is /usr/bin/ls

operator@srv-tramontana:~$ type grep
grep is /usr/bin/grep

type -a shows all the possible resolutions, in order of priority. It is the diagnostic tool for when a command "does not do what it should": there is nearly always an alias or a script sitting in front of the real program.

Tool What it does When to use it
type <cmd> Says what it is: builtin, alias, function or file Diagnosis. The most complete
type -a <cmd> All resolutions, by priority When you suspect an alias or a duplicate
which <cmd> Path of the external executable Quick, but it ignores builtins and aliases
command -v <cmd> Resolution in one line In scripts: it is POSIX and portable
operator@srv-tramontana:~$ which cd
operator@srv-tramontana:~$ echo $?
1

which cd returns nothing and fails, because cd is not a file. That is exactly the limitation that makes which useless as a general diagnostic tool.

Why cd has to be a builtin

This question comes up in technical interviews, and its answer explains something real about how the system works.

Every process on Linux has its own working directory, which is a private attribute of the process. When you run an external program, the shell creates a child process and that child inherits a copy of the parent's environment. The child can change whatever it likes in its copy: when it finishes, its copy disappears and the parent carries on exactly as before.

flowchart LR
    A[Bash<br/>cwd = /home/operator] -->|creates child| B[Child process<br/>cwd = /home/operator]
    B -->|changes its cwd| C[Child process<br/>cwd = /etc]
    C -->|finishes| D[Bash<br/>cwd = /home/operator<br/>UNCHANGED]

If cd were an external program, it would change the directory of its own process and die immediately. Your shell would never move. That is why cd has to run inside the shell's own process, that is, be a builtin.

The same logic applies to export, alias, source, exit, umask and history: anything that modifies the state of the shell must be internal. Keep hold of this idea, because it is what explains why a script cannot change the directory of whoever calls it (Module 4).

  1. How the shell finds an executable

When you type grep, the shell does not comb the disk. It follows a strict order:

  1. Is it an alias? It substitutes it.
  2. Is it a shell function? It runs it.
  3. Is it a builtin? It runs it.
  4. If not, it looks for an executable file with that name in the directories listed in the PATH variable, in order, and uses the first one it finds.
  5. If it does not find it: command not found.
operator@srv-tramontana:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

These are directories separated by :. It is a list of places to look, not a search across the whole disk. Two practical consequences:

  • A program sitting in a directory outside the PATH will not run just by typing its name. You have to give its path: that is why your scripts in /home/operator/scripts will be launched as ./report.sh or with the full path.
  • The order matters. If there were two executables with the same name in two PATH directories, the one appearing first wins.

The current directory is not in the PATH, and that is a deliberate security decision: if it were, leaving a file called ls in a shared directory would be enough to trick anyone who walked in. Never add . to the PATH.

The full detail of PATH (how it is modified, where it is defined and what exactly an environment variable is) is the subject of lesson 03-01. Here the concept is enough.

  1. Tab completion

The Tab key is the one that will improve your speed the most, and not only by saving keystrokes: completing with Tab prevents typos. If the name completes by itself, it exists.

How it works:

  • One press with a single match: it completes the rest.
  • One press with several matches: it completes the common part and stops there (usually with a beep).
  • Two presses: it shows the list of all the matches.
operator@srv-tramontana:~$ cd /var/log/tram<Tab>
operator@srv-tramontana:~$ cd /var/log/tramontana/

operator@srv-tramontana:~$ ls /var/log/tramontana/<Tab><Tab>
access.log   errors.log

operator@srv-tramontana:~$ ls /var/log/tramontana/a<Tab>
operator@srv-tramontana:~$ ls /var/log/tramontana/access.log

What it completes according to the position in the line:

Position What it offers
First word Commands, builtins, aliases and functions
After a command Files and directories
After ~ User names: ~ope<Tab> → ~operator/
After $ Variable names
After - or -- The command's options (if completion is installed)

That last row depends on the bash-completion package, present by default in Ubuntu Server 24.04. Thanks to it, many commands complete their own options and even their arguments:

operator@srv-tramontana:~$ systemctl --stat<Tab>
operator@srv-tramontana:~$ systemctl --state=

A hygiene tip: if you type a whole long name without Tab and it then fails, you have wasted your time twice. Type three letters and press Tab. If it does not complete, the file is not where you think it is, and you have just found the mistake before running anything.

  1. The command history

Bash keeps what you run in memory during the session and dumps it to the ~/.bash_history file on exit. That means you never have to retype the same thing twice.

operator@srv-tramontana:~$ history
  ...
  147  df -h
  148  ls -l /var/log/tramontana
  149  uptime
  150  history

operator@srv-tramontana:~$ history 3
  149  uptime
  150  history
  151  history 3

Ways of reusing the history:

Shortcut What it does
Up / down arrow Walks through the history backwards and forwards
Ctrl+R Incremental reverse search: type a fragment and the command appears
Ctrl+R again Jumps to the previous match
Ctrl+G or Ctrl+C Cancels the search and leaves the line as it was
!! The whole of the last command
!148 Command number 148 in the history
!ls The last command that started with ls
!$ The last argument of the previous command
!* All the arguments of the previous command

Ctrl+R is, by some distance, the most profitable shortcut in this section. Press Ctrl+R, type tram and Bash shows you the most recent command containing that string. Press Enter to run it or the right arrow to edit it first.

The two most useful idioms in day-to-day work are !! and !$:

operator@srv-tramontana:~$ cat /etc/tramontana/app.conf
cat: /etc/tramontana/app.conf: Permission denied

operator@srv-tramontana:~$ sudo !!
sudo cat /etc/tramontana/app.conf
[sudo] password for operator:
# Tramontana Bookings configuration
db_host=127.0.0.1
...

sudo !! reruns the previous command with privileges. Bash shows the expanded line before running it, which gives you the chance to see what is about to happen.

operator@srv-tramontana:~$ ls -l /var/log/tramontana/access.log
-rw-r----- 1 root adm 18432 Aug 18 09:14 /var/log/tramontana/access.log

operator@srv-tramontana:~$ sudo tail -n 3 !$
sudo tail -n 3 /var/log/tramontana/access.log
2026-08-18 09:14:02 GET /bookings 200 user=mvidal
2026-08-18 09:14:07 POST /bookings 201 house=mas-figueres
2026-08-18 09:14:11 GET /houses 200 user=anon

!$ recovers the last argument: the classic "look first, act second" pattern without retyping the path.

A security warning worth taking on board right now: the history is a plain text file. If you type a password as an argument to a command, it is saved in ~/.bash_history. Never pass secrets on the command line; the correct handling of credentials is covered in lesson 06-05.

  1. Editing the command line without suffering

Bash uses the readline library, which brings the editing shortcuts of the Emacs editor. The same shortcuts work in many other terminal programs, so learning them pays off beyond the shell.

Shortcut Action
Ctrl+A Go to the beginning of the line
Ctrl+E Go to the end of the line
Alt+B Move back one word
Alt+F Move forward one word
Ctrl+W Delete the word before the cursor
Ctrl+U Delete from the cursor back to the beginning
Ctrl+K Delete from the cursor to the end
Ctrl+Y Paste back the last thing you deleted with W, U or K
Alt+D Delete the next word
Ctrl+T Swap the two characters around the cursor
Ctrl+_ Undo the last edit
Ctrl+L Clear the screen (keeping the line)

A mnemonic: A for the start of the alphabet, E for end, K for kill to the end, U for undo back to the beginning, W for word.

The most frequent practical case: you type a long command, spot a typo at the beginning and you are at the end. Instead of holding down backspace, Ctrl+A, fix it, Ctrl+E, Enter. And if the whole line is wrong: Ctrl+U wipes it in one go.

A useful detail: in many terminal emulators Alt works directly; if it does not, the alternative is to press Esc and release it before the letter (Esc then B is equivalent to Alt+B).

  1. Chaining commands: ;, &&, || and grouping

You can put several commands on a single line, and the difference between the separators is not cosmetic: it is control logic.

To understand it you need the exit code: every command, when it finishes, returns a number. 0 means success; any other value means failure. You check it with $? (we will develop this in lesson 02-02).

Operator Name Behaviour
; Sequence Runs the next one always, whatever happens
&& Logical AND Runs the next one only if the previous one succeeded (code 0)
|| Logical OR Runs the next one only if the previous one failed (code ≠ 0)
operator@srv-tramontana:~$ cd /directory/that/does/not/exist ; echo "still here"
-bash: cd: /directory/that/does/not/exist: No such file or directory
still here

operator@srv-tramontana:~$ cd /directory/that/does/not/exist && echo "still here"
-bash: cd: /directory/that/does/not/exist: No such file or directory

operator@srv-tramontana:~$ cd /directory/that/does/not/exist || echo "could not get in"
-bash: cd: /directory/that/does/not/exist: No such file or directory
could not get in

The difference is critical in practice. Compare these two lines:

cd /srv/tramontana/backups ; rm -r old
cd /srv/tramontana/backups && rm -r old

If the directory does not exist, the first one changes its mind but not its intention: it does not get in, and it deletes old in whatever directory you happened to be in, which may be your home directory. The second does nothing. A rule to adopt from today: when a command depends on the previous one having worked, use &&, never ;.

The three can be combined, and you can also group with parentheses:

operator@srv-tramontana:~$ ls /opt/tramontana/app && echo "OK: the app is there" || echo "WARNING: the app is missing"
executable  templates  version.txt
OK: the app is there

Parentheses group commands in a subshell: a child process with its own working directory and its own state.

operator@srv-tramontana:~$ pwd
/home/operator
operator@srv-tramontana:~$ (cd /var/log/tramontana && ls)
access.log  errors.log
operator@srv-tramontana:~$ pwd
/home/operator

The cd inside the parentheses affected only the subshell; when it comes back, you are still where you were. It is exactly the mechanism from section 4, now used in your favour: go in, do something, and do not let the cd contaminate your session.

With braces { ...; } you group without creating a subshell (the changes do affect your session). It is a distinction we will pick up again when writing scripts in Module 4.

  1. Running in the background with &

An & at the end of a command launches it in the background: the shell does not wait for it to finish and gives you the prompt back immediately.

operator@srv-tramontana:~$ sleep 60 &
[1] 4127
operator@srv-tramontana:~$ jobs
[1]+  Running                 sleep 60 &
operator@srv-tramontana:~$ fg %1
sleep 60
  • [1] is the job number within this session; 4127 is the process's PID in the system.
  • jobs lists the session's jobs, fg brings one to the foreground and bg resumes a stopped one in the background.
  • Ctrl+Z stops (does not kill) the foreground process and gives you the prompt back.

These are only the notions you need to recognise the syntax. Full job control, processes, signals and what happens to a background process when you close the session are the subject of lesson 03-06.

  1. Quoting and escaping: when the name has spaces

Go back to the REPL cycle in section 2: the shell splits the line by spaces before running anything. That is the explanation for a classic mistake:

operator@srv-tramontana:~$ ls
august report.txt  bookings.csv

operator@srv-tramontana:~$ rm august report.txt
rm: cannot remove 'august': No such file or directory
rm: cannot remove 'report.txt': No such file or directory

rm never saw a name with a space: it received two arguments, august and report.txt. The shell did its job; the problem is that you did not tell it the space was part of the name.

Three ways to fix it:

rm 'august report.txt'      # single quotes
rm "august report.txt"      # double quotes
rm august\ report.txt       # backslash escaping the space

And the fourth, the one you will actually use: type aug and press Tab. Bash completes the name and escapes the space for you.

The difference between the three mechanisms:

Mechanism What it protects What is still interpreted
'single quotes' Everything, literally Nothing. You cannot even put a single quote inside
"double quotes" Spaces and wildcards $variable, `command`, $(command) and \
\ (backslash) The next character The rest of the line
operator@srv-tramontana:~$ echo 'The user is $USER'
The user is $USER
operator@srv-tramontana:~$ echo "The user is $USER"
The user is operator

The practical rule until Module 3 is simple: if you want the text exactly as it is, single quotes; if you expect something inside to be substituted, double quotes. Why it is substituted and what else can be substituted is the content of lesson 03-01.

A point of style that applies to srv-tramontana: do not put spaces in file names on a server. Use hyphens or underscores (august-report.txt). This is not fussiness: every space is a trap waiting for someone to write a script without quotes.

  1. Cancelling and exiting

Three keystrokes that need telling apart properly, because they are often confused:

Combination What it does When to use it
Ctrl+C Sends the interrupt signal to the foreground program A command has hung or is taking too long
Ctrl+D Sends end of input (EOF) Finishing typing data; on an empty line, it closes the session
exit Ends the shell explicitly Closing the session cleanly, above all over SSH
Ctrl+Z Stops (does not kill) the process and leaves it in the background Parking something for a moment; you pick it up again with fg

The difference between Ctrl+C and Ctrl+D matters: Ctrl+C interrupts, Ctrl+D says there is no more data. If a command seems to be hanging without doing anything, very often it is waiting for you to type something at the keyboard and the right way out is Ctrl+D, not Ctrl+C.

And Ctrl+Z kills nothing, it only suspends. It is a frequent mistake to believe you have closed an editor with Ctrl+Z when in fact you have left it stopped in the background, holding the file locked.

Common Mistakes and Tips

Using ; where && was called for. It is the mistake in this chapter with the most serious consequences, because it only shows up when something fails, that is, at the worst possible moment. Chain with && by default.

Typing long paths by hand. Every character typed is an opportunity for a typo. Always Tab.

Trusting which to diagnose. It does not see builtins or aliases. If something behaves oddly, type -a is the answer.

Forgetting that Linux is case-sensitive. Bookings.csv and bookings.csv are two different files. Coming from Windows, this bites during the first few weeks.

Unprotected spaces. If a name has spaces and you do not quote it, the shell will see several arguments. And if the command was rm, it will delete things you did not want deleted.

Copying commands from the internet without reading them. Especially those starting with sudo or containing rm -rf. Before running something you do not understand, read it in full and, if need be, look it up in the manual (lesson 02-02).

Tip: run the harmless command first. Are you about to delete using a pattern? Run ls with the same pattern first and see what comes out. Then press the up arrow, change ls for rm and run it. It is the habit that separates those who have lost data from those who have not.

Tip: split a long line over several. A backslash at the end of the line lets you continue on the next one, and it makes complex commands far more readable when you paste them into documentation.

Tip: Ctrl+L instead of clear. It is faster and you do not lose the line you were typing.

Exercises

Exercise 1: reconnaissance of the shell

On srv-tramontana, answer with commands (not from memory):

  1. Is echo a builtin, an external program, or both?
  2. How many directories are there in your PATH?
  3. Does ls have an alias defined? Which one?
  4. Why does which cd return nothing?

Exercise 2: Luis's trap

Luis Ferrer sends you this line over chat to clean up the application's temporary dumps, saying he "tested it on his laptop and it works fine":

cd /srv/tramontana/backups/temp ; rm -r *

Explain what can go wrong, rewrite it safely and add a prior check that shows you what is going to be deleted before deleting it.

Exercise 3: keyboard speed

Without using the mouse and without deleting character by character:

  1. Type ls -l /var/log/tramontana/access.log and run it.
  2. Now run wc -l on that same file without retyping the path.
  3. Recover the first command from the history and modify it to show errors.log instead of access.log, using only editing shortcuts.
  4. Create a file called marta report.txt, check that it exists and delete it. Explain why the name is a bad idea on a server.

Solutions

Solution 1

operator@srv-tramontana:~$ type -a echo
echo is a shell builtin
echo is /usr/bin/echo

Both. Bash has its own echo builtin and /usr/bin/echo also exists. The builtin wins, because internal commands take priority over the PATH. It is a frequent case: echo, test, kill and printf exist in both forms, and their options do not always match between them, which explains some baffling behaviour in scripts ported from one system to another.

operator@srv-tramontana:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

Six directories, separated by :. You can count them by eye; in Module 3 you will see how to do it with a command.

operator@srv-tramontana:~$ type ls
ls is aliased to `ls --color=auto'

Yes: Ubuntu defines ls --color=auto in ~/.bashrc. That is why your directories come out in blue: it is not ls doing it on its own, it is the alias. Aliases are covered in 03-01.

which cd returns nothing because cd is not a file on disk: it is a builtin. And it has to be one, because it must change the working directory of the shell's own process, something a child process cannot do to its parent.

Solution 2

What can go wrong. The semicolon runs rm -r * whatever happens with the cd. If /srv/tramontana/backups/temp does not exist, is misspelled, or the directory has been renamed, cd fails and rm -r * runs in the current directory. If at that moment you were in /home/operator, you have just deleted your home directory, including /home/operator/scripts. If you were in /opt/tramontana, you have taken the application out with it.

The fact that it "works on Luis's laptop" is precisely the warning sign: it works as long as the directory exists. The failure appears the day it does not, which is the day nobody is watching.

Safe version:

# 1. Look first, without touching anything
operator@srv-tramontana:~$ ls -la /srv/tramontana/backups/temp
total 12
drwxr-x--- 2 operator operator 4096 Aug 18 08:30 .
drwxr-x--- 3 operator operator 4096 Aug 18 08:30 ..
-rw-r----- 1 operator operator  842 Aug 17 23:00 dump-2026-08-17.tmp

# 2. Chain with && and use -I, which asks for ONE confirmation if there are many files
operator@srv-tramontana:~$ cd /srv/tramontana/backups/temp && rm -rI ./*

Improvements applied:

  • && instead of ;: if the cd fails, nothing is deleted. This is the important change.
  • ls -la first: you see exactly what is there before destroying it.
  • ./* instead of *: it protects against names starting with a hyphen.
  • -I: it asks for a single confirmation when there are more than three items. Less annoying than -i and enough to make you stop and think.

An even better alternative, which avoids the cd entirely and does not leave your session in another directory:

operator@srv-tramontana:~$ (cd /srv/tramontana/backups/temp && ls -la && rm -rI ./*)

How you would put it to Luis: not that his command is badly written, but that it is missing the condition. The ; says "do this and then that"; && says "do that only if this went well". In a clean-up with rm -r, that difference is what separates routine maintenance from an incident.

Solution 3

operator@srv-tramontana:~$ ls -l /var/log/tramontana/access.log
-rw-r----- 1 root adm 18432 Aug 18 09:14 /var/log/tramontana/access.log

operator@srv-tramontana:~$ sudo wc -l !$
sudo wc -l /var/log/tramontana/access.log
412 /var/log/tramontana/access.log

!$ recovers the last argument of the previous command. Bash shows the line already expanded before running it, which lets you verify that it points where you think it does.

For point 3, the sequence with shortcuts:

  1. Up arrow twice (or Ctrl+R and type access) until you recover ls -l /var/log/tramontana/access.log.
  2. Ctrl+W deletes the last word, which in this case is the whole path back to the preceding space. Since you only want to change the file name, this is cleaner: Alt+B to move back word by word until you are on access, delete that word with Alt+D and type errors.
  3. Enter.
operator@srv-tramontana:~$ ls -l /var/log/tramontana/errors.log
-rw-r----- 1 root adm 6348 Aug 18 09:02 /var/log/tramontana/errors.log

With long names, Ctrl+A to go to the beginning and Alt+F to move forward word by word is usually quicker than holding down the left arrow.

For point 4:

operator@srv-tramontana:~$ touch 'marta report.txt'
operator@srv-tramontana:~$ ls -l marta*
-rw-rw-r-- 1 operator operator 0 Aug 18 10:22 'marta report.txt'
operator@srv-tramontana:~$ rm 'marta report.txt'

Notice that Ubuntu's ls shows the name in quotes precisely to warn you that it contains a space.

Why it is a bad idea on a server: the file works perfectly well as long as you handle it by hand with Tab, but the day it turns up in a script without quotes it will break, and it will do so in the worst possible way: not by failing, but by treating marta and report.txt as two paths. In an rm, that is a wrong deletion; in a copy loop, a file that does not get backed up. The professional convention is marta-report.txt or marta_report.txt.

Conclusion

You are no longer looking at a black screen: you are handling an interpreter whose workings you understand.

  • The CLI is the professional tool because it is reproducible, automatable, remote and lightweight, not out of tradition; and its honest downside is that it neither forgives nor warns.
  • The shell follows a REPL cycle in which it expands before executing: the program never sees exactly what you typed.
  • A command has three parts, its options can be short, grouped, long or value-taking, and -- closes the list of options.
  • There are builtins and external commands; type -a is your diagnostic tool, and cd has to be a builtin because no child can move its parent.
  • The shell locates executables by walking the PATH in order, and the current directory is not there for security reasons.
  • Tab saves you keystrokes and, above all, typos; Ctrl+R, !! and !$ save you retyping; the readline shortcuts save you the endless backspace.
  • ;, && and || are control logic, not punctuation: && is your default option when one command depends on the previous one.
  • Spaces in names are protected with single quotes, double quotes or a backslash, and the best thing is not to have them at all.

With this you can write commands fluently. What is missing is the other pillar of self-sufficiency: knowing what commands exist and what each option does without depending on a search engine. In the next lesson, Getting Help and System Documentation, you will learn to read a man page from start to finish, to understand the notation of the SYNOPSIS, to move around the eight sections of the manual, to find a command when you do not even know its name, and to resolve a real question from Luis Ferrer using nothing but what is already installed on srv-tramontana. It is the lesson that turns "I don't know how to do it" into "I don't know it yet".

Linux Course: From Beginner to System Administrator

Module 1: Introduction to Linux

Module 2: Basic Linux Commands

Module 3: Advanced Command-Line Skills

Module 4: Shell Scripting

Module 5: System Administration

Module 6: Networking and Security

Module 7: Advanced Topics

Module 8: Practical Projects

© Copyright 2026. All rights reserved